@stacksjs/auth 0.70.22 → 0.70.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,43 @@
1
+ import { User } from '@stacksjs/orm';
2
+ import type { AuthCredentials, AuthToken, NewAccessToken, PersonalAccessToken, TokenCreateOptions } from '@stacksjs/types';
3
+ declare type UserModel = InstanceType<typeof User>;
4
+ export declare class Auth {
5
+ static attempt(credentials: AuthCredentials): Promise<boolean>;
6
+ static validate(credentials: AuthCredentials): Promise<boolean>;
7
+ static login(credentials: AuthCredentials, options?: TokenCreateOptions): Promise<
8
+ { user: UserModel, token: AuthToken, refreshToken?: string, expiresIn?: number } | null
9
+ >;
10
+ static loginUsingId(userId: number, options?: TokenCreateOptions): Promise<
11
+ { user: UserModel, token: AuthToken, refreshToken?: string, expiresIn?: number } | null
12
+ >;
13
+ static logout(): Promise<void>;
14
+ static user(): Promise<UserModel | undefined>;
15
+ static check(): Promise<boolean>;
16
+ static guest(): Promise<boolean>;
17
+ static id(): Promise<number | undefined>;
18
+ static setUser(user: UserModel): void;
19
+ static createTokenForUser(user: UserModel, options?: TokenCreateOptions): Promise<NewAccessToken>;
20
+ static createToken(user: UserModel, name?: string, abilities?: string[]): Promise<AuthToken>;
21
+ static requestToken(credentials: AuthCredentials, clientId: number, clientSecret: string): Promise<{ token: AuthToken } | null>;
22
+ static validateToken(token: string): Promise<boolean>;
23
+ static getUserFromToken(token: string): Promise<UserModel | undefined>;
24
+ static currentAccessToken(): Promise<PersonalAccessToken | undefined>;
25
+ static tokenCan(ability: string): Promise<boolean>;
26
+ static tokenCant(ability: string): Promise<boolean>;
27
+ static tokenAbilities(): Promise<string[]>;
28
+ static tokenCanAll(abilities: string[]): Promise<boolean>;
29
+ static tokenCanAny(abilities: string[]): Promise<boolean>;
30
+ static tokens(userId?: number): Promise<PersonalAccessToken[]>;
31
+ static revokeToken(token: string): Promise<void>;
32
+ static revokeTokenById(tokenId: number): Promise<void>;
33
+ static revokeAllTokens(userId?: number): Promise<void>;
34
+ static revokeOtherTokens(userId?: number): Promise<void>;
35
+ static pruneExpiredTokens(): Promise<number>;
36
+ static pruneRevokedTokens(): Promise<number>;
37
+ static rotateToken(oldToken: string): Promise<AuthToken | null>;
38
+ static findToken(tokenId: number): Promise<PersonalAccessToken | null>;
39
+ static once(credentials: AuthCredentials): Promise<boolean>;
40
+ static guard(_name?: string): typeof Auth;
41
+ static viaRemember(): boolean;
42
+ static clearState(): void;
43
+ }
@@ -0,0 +1,17 @@
1
+ export declare function generateTwoFactorSecret(): string;
2
+ export declare function generateTwoFactorToken(secret: Secret): Promise<Token>;
3
+ export declare function verifyTwoFactorCode(token: Token, secret: Secret): Promise<boolean>;
4
+ /**
5
+ * Generate an otpauth:// URI for two-factor authentication
6
+ *
7
+ * This URI can be used with any QR code library to generate a scannable
8
+ * QR code for authenticator apps.
9
+ *
10
+ * @param user - User identifier (email or username)
11
+ * @param service - Service name (e.g., 'StacksJS 2FA')
12
+ * @param secret - Optional secret (will be generated if not provided)
13
+ * @returns The otpauth:// URI string
14
+ */
15
+ export declare function generateTwoFactorUri(user?: string, service?: string, secret?: Secret): string;
16
+ export type Token = string;
17
+ export type Secret = string;
@@ -0,0 +1,77 @@
1
+ import { any, can, cannot } from './gate';
2
+ import type { AuthorizationResponse } from './gate';
3
+ import type { UserModel as OrmUserModel } from '@stacksjs/orm';
4
+ /**
5
+ * Check if a user can perform an ability
6
+ *
7
+ * @example
8
+ * if (await userCan(user, 'edit-settings')) { ... }
9
+ * if (await userCan(user, 'update', post)) { ... }
10
+ */
11
+ export declare function userCan(user: UserModel | null, ability: string, ...args: any[]): Promise<boolean>;
12
+ /**
13
+ * Check if a user cannot perform an ability
14
+ *
15
+ * @example
16
+ * if (await userCannot(user, 'delete', post)) { ... }
17
+ */
18
+ export declare function userCannot(user: UserModel | null, ability: string, ...args: any[]): Promise<boolean>;
19
+ /**
20
+ * Check if a user can perform any of the given abilities
21
+ *
22
+ * @example
23
+ * if (await userCanAny(user, ['update', 'delete'], post)) { ... }
24
+ */
25
+ export declare function userCanAny(user: UserModel | null, abilities: string[], ...args: any[]): Promise<boolean>;
26
+ /**
27
+ * Check if a user can perform all of the given abilities
28
+ *
29
+ * @example
30
+ * if (await userCanAll(user, ['view', 'update'], post)) { ... }
31
+ */
32
+ export declare function userCanAll(user: UserModel | null, abilities: string[], ...args: any[]): Promise<boolean>;
33
+ /**
34
+ * Authorize a user or throw an exception
35
+ *
36
+ * @example
37
+ * await authorizeUser(user, 'update', post) // Throws if not allowed
38
+ */
39
+ export declare function authorizeUser(user: UserModel | null, ability: string, ...args: any[]): Promise<AuthorizationResponse>;
40
+ /**
41
+ * Get detailed authorization result
42
+ *
43
+ * @example
44
+ * const result = await inspectUser(user, 'update', post)
45
+ * if (result.denied()) {
46
+ * console.log(result.message)
47
+ * }
48
+ */
49
+ export declare function inspectUser(user: UserModel | null, ability: string, ...args: any[]): Promise<AuthorizationResponse>;
50
+ /**
51
+ * Authorizable trait for user models
52
+ *
53
+ * Add authorization methods to a user object
54
+ *
55
+ * @example
56
+ * const authorizedUser = withAuthorization(user)
57
+ * if (await authorizedUser.can('update', post)) { ... }
58
+ */
59
+ export declare function withAuthorization<T extends UserModel>(user: T): T & AuthorizableMethods;
60
+ /**
61
+ * Authorization methods interface
62
+ */
63
+ export declare interface AuthorizableMethods {
64
+ can(ability: string, ...args: any[]): Promise<boolean>
65
+ cannot(ability: string, ...args: any[]): Promise<boolean>
66
+ canAny(abilities: string[], ...args: any[]): Promise<boolean>
67
+ canAll(abilities: string[], ...args: any[]): Promise<boolean>
68
+ authorize(ability: string, ...args: any[]): Promise<AuthorizationResponse>
69
+ }
70
+ // Alias the ORM-derived UserModel under the name the rest of this module
71
+ // expects. Using the row/instance shape (rather than `typeof User`) lets
72
+ // callers pass plain authenticated user objects to the gate helpers.
73
+ declare type UserModel = OrmUserModel;
74
+ /**
75
+ * Type for a user with authorization methods
76
+ */
77
+ export type AuthorizableUser<T extends UserModel> = T & AuthorizableMethods;
@@ -0,0 +1,2 @@
1
+ import type { Result } from '@stacksjs/error-handling';
2
+ export declare function createPersonalAccessClient(): Promise<Result<string, never>>;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Check if a user's email is verified
3
+ */
4
+ export declare function isEmailVerified(user: { email_verified_at?: string | Date | null }): boolean;
5
+ /**
6
+ * Send a verification email to the user
7
+ */
8
+ export declare function sendVerificationEmail(user: { id: number, email: string, name?: string }): Promise<void>;
9
+ /**
10
+ * Verify a user's email with the provided token
11
+ */
12
+ export declare function verifyEmail(userId: number, token: string): Promise<EmailVerificationResult>;
13
+ /**
14
+ * Resend verification email with rate limiting
15
+ */
16
+ export declare function resendVerificationEmail(user: { id: number, email: string, name?: string, email_verified_at?: string | Date | null }): Promise<EmailVerificationResult>;
17
+ /**
18
+ * Email verification facade
19
+ */
20
+ export declare const EmailVerification: {
21
+ isVerified: unknown;
22
+ send: unknown;
23
+ verify: unknown;
24
+ resend: unknown
25
+ };
26
+ export declare interface EmailVerificationResult {
27
+ success: boolean
28
+ message?: string
29
+ }
@@ -0,0 +1,161 @@
1
+ import type { UserModel as OrmUserModel } from '@stacksjs/orm';
2
+ /**
3
+ * Define a new authorization gate
4
+ *
5
+ * @example
6
+ * define('edit-settings', (user) => user?.isAdmin)
7
+ * define('update-post', (user, post) => user?.id === post.userId)
8
+ */
9
+ export declare function define<T = any>(ability: string, callback: GateCallback<T>): void;
10
+ /**
11
+ * Register a policy for a model
12
+ *
13
+ * @example
14
+ * policy('Post', PostPolicy)
15
+ * policy(Post, PostPolicy)
16
+ */
17
+ export declare function policy(model: string | { name: string }, policyClass: new () => Policy): void;
18
+ /**
19
+ * Register a callback to run before all gate checks
20
+ *
21
+ * @example
22
+ * before((user, _ability) => {
23
+ * if (user?.isSuperAdmin) return true // Super admins can do anything
24
+ * return null // Continue to normal checks
25
+ * })
26
+ */
27
+ export declare function before(callback: (user: UserModel | null, ability: string, args: any[]) => boolean | null | Promise<boolean | null>): void;
28
+ /**
29
+ * Register a callback to run after all gate checks
30
+ */
31
+ export declare function after(callback: (user: UserModel | null, ability: string, result: boolean, args: any[]) => boolean | void | Promise<boolean | void>): void;
32
+ /**
33
+ * Check if the user is allowed to perform an ability
34
+ *
35
+ * @example
36
+ * if (await allows('edit-settings', user)) { ... }
37
+ * if (await allows('update', user, post)) { ... }
38
+ */
39
+ export declare function allows(ability: string, user: UserModel | null, ...args: any[]): Promise<boolean>;
40
+ /**
41
+ * Check if the user is denied from performing an ability
42
+ *
43
+ * @example
44
+ * if (await denies('delete', user, post)) { ... }
45
+ */
46
+ export declare function denies(ability: string, user: UserModel | null, ...args: any[]): Promise<boolean>;
47
+ /**
48
+ * Check if the user can perform an ability (alias for allows)
49
+ */
50
+ export declare function can(ability: string, user: UserModel | null, ...args: any[]): Promise<boolean>;
51
+ /**
52
+ * Check if the user cannot perform an ability (alias for denies)
53
+ */
54
+ export declare function cannot(ability: string, user: UserModel | null, ...args: any[]): Promise<boolean>;
55
+ /**
56
+ * Check if the user can perform any of the given abilities
57
+ *
58
+ * @example
59
+ * if (await any(['update', 'delete'], user, post)) { ... }
60
+ */
61
+ export declare function any(abilities: string[], user: UserModel | null, ...args: any[]): Promise<boolean>;
62
+ /**
63
+ * Check if the user can perform all of the given abilities
64
+ *
65
+ * @example
66
+ * if (await all(['view', 'update'], user, post)) { ... }
67
+ */
68
+ export declare function all(abilities: string[], user: UserModel | null, ...args: any[]): Promise<boolean>;
69
+ /**
70
+ * Check if the user can perform none of the given abilities
71
+ */
72
+ export declare function none(abilities: string[], user: UserModel | null, ...args: any[]): Promise<boolean>;
73
+ /**
74
+ * Authorize an ability or throw an exception
75
+ *
76
+ * @example
77
+ * await authorize('update', user, post) // Throws if not allowed
78
+ */
79
+ export declare function authorize(ability: string, user: UserModel | null, ...args: any[]): Promise<AuthorizationResponse>;
80
+ /**
81
+ * Get detailed inspection result for an ability check
82
+ */
83
+ export declare function inspect(ability: string, user: UserModel | null, ...args: any[]): Promise<AuthorizationResponse>;
84
+ /**
85
+ * Get a policy instance for a model
86
+ */
87
+ export declare function getPolicyFor<T = any>(model: T): Policy<T> | null;
88
+ /**
89
+ * Check if a gate is defined
90
+ */
91
+ export declare function has(ability: string): boolean;
92
+ /**
93
+ * Check if a policy is registered for a model
94
+ */
95
+ export declare function hasPolicy(model: string | { name: string }): boolean;
96
+ /**
97
+ * Get all defined gate names
98
+ */
99
+ export declare function abilities(): string[];
100
+ /**
101
+ * Clear all gates and policies (useful for testing)
102
+ */
103
+ export declare function flush(): void;
104
+ /**
105
+ * Gate facade for convenient access
106
+ */
107
+ export declare const Gate: {
108
+
109
+ };
110
+ /**
111
+ * Policy class interface
112
+ */
113
+ export declare interface Policy<T = any> {
114
+ before?(user: UserModel | null, ability: string): boolean | null | Promise<boolean | null>
115
+ viewAny?(user: UserModel | null): boolean | Promise<boolean> | AuthorizationResponse
116
+ view?(user: UserModel | null, model: T): boolean | Promise<boolean> | AuthorizationResponse
117
+ create?(user: UserModel | null): boolean | Promise<boolean> | AuthorizationResponse
118
+ update?(user: UserModel | null, model: T): boolean | Promise<boolean> | AuthorizationResponse
119
+ delete?(user: UserModel | null, model: T): boolean | Promise<boolean> | AuthorizationResponse
120
+ restore?(user: UserModel | null, model: T): boolean | Promise<boolean> | AuthorizationResponse
121
+ forceDelete?(user: UserModel | null, model: T): boolean | Promise<boolean> | AuthorizationResponse
122
+ [key: string]: PolicyMethod | undefined
123
+ }
124
+ // Alias the ORM-derived UserModel under the name this module uses internally.
125
+ // The gate API receives authenticated user objects (rows / instances),
126
+ // not the User class constructor.
127
+ declare type UserModel = OrmUserModel;
128
+ /**
129
+ * Gate callback function type
130
+ */
131
+ export type GateCallback<T = any> = (_user: UserModel | null, ..._args: T[]) => boolean | Promise<boolean> | AuthorizationResponse;
132
+ /**
133
+ * Policy method type. The return type intentionally allows `null` so that
134
+ * a policy's `before()` hook (which returns `null` to delegate to the
135
+ * underlying ability check) is index-compatible with the catch-all
136
+ * `[key: string]: PolicyMethod | undefined` signature on `Policy`.
137
+ */
138
+ export type PolicyMethod<T = any> = (_user: UserModel | null, _model?: T, ..._args: any[]) => boolean | null | Promise<boolean | null> | AuthorizationResponse;
139
+ /**
140
+ * Authorization response for detailed allow/deny
141
+ */
142
+ export declare class AuthorizationResponse {
143
+ readonly isAllowed: boolean;
144
+ readonly message?: string;
145
+ readonly code?: string;
146
+ constructor(allowed: boolean, message?: string, code?: string);
147
+ static allow(message?: string): AuthorizationResponse;
148
+ static deny(message?: string, code?: string): AuthorizationResponse;
149
+ allowed(): boolean;
150
+ denied(): boolean;
151
+ authorize(): void;
152
+ }
153
+ /**
154
+ * Authorization exception
155
+ */
156
+ export declare class AuthorizationException extends Error {
157
+ public readonly code?: string;
158
+ public readonly status?: number;
159
+ constructor(message?: string, code?: string, status?: number);
160
+ }
161
+ export default Gate;
@@ -0,0 +1,29 @@
1
+ export * from './authentication';
2
+ export * from './authenticator';
3
+ export * from './client';
4
+ export * from './middleware';
5
+ export * from './rate-limiter';
6
+ // WebAuthn/Passkey support (now using ts-auth - no external dependencies)
7
+ export * from './passkey';
8
+ export * from './password/reset';
9
+ export * from './register';
10
+ export * from './user';
11
+ // Token management (Laravel Passport-style)
12
+ export * from './tokens';
13
+ // Authorization Gates & Policies (Laravel-style)
14
+ export * from './gate';
15
+ export * from './policy';
16
+ export * from './authorizable';
17
+ // Role-Based Access Control (RBAC)
18
+ export * from './rbac';
19
+ // Email Verification
20
+ export * from './email-verification';
21
+ // Session-based Authentication (SPA Cookie Auth)
22
+ export * from './session-auth';
23
+ // TOTP (Two-Factor Authentication) - re-export from ts-auth
24
+ export {
25
+ generateTOTP,
26
+ verifyTOTP,
27
+ generateTOTPSecret,
28
+ totpKeyUri,
29
+ } from '@stacksjs/ts-auth';
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Built-in auth middleware handler
3
+ * Validates bearer token and sets the authenticated user on Auth
4
+ */
5
+ export declare function authMiddleware(request: any): Promise<void>;
6
+ /**
7
+ * Auth middleware object with handle method (for compatibility with middleware loader)
8
+ * @defaultValue `{ name: 'auth' }`
9
+ */
10
+ export declare const authMiddlewareHandler: {
11
+ /** @defaultValue 'auth' */
12
+ name: string;
13
+ handle: unknown
14
+ };
@@ -0,0 +1,46 @@
1
+ import { User } from '@stacksjs/orm';
2
+ import type { Insertable } from '@stacksjs/database';
3
+ import type { VerifiedRegistrationResponse } from '@stacksjs/ts-auth';
4
+ // Re-export WebAuthn types from ts-auth
5
+ export type {
6
+ VerifiedRegistrationResponse,
7
+ VerifiedAuthenticationResponse,
8
+ RegistrationCredential,
9
+ AuthenticationCredential,
10
+ PublicKeyCredentialCreationOptions,
11
+ PublicKeyCredentialRequestOptions,
12
+ RegistrationOptions,
13
+ AuthenticationOptions,
14
+ } from '@stacksjs/ts-auth';
15
+ export declare function getUserPasskeys(userId: number): Promise<PasskeyAttribute[]>;
16
+ export declare function getUserPasskey(userId: number, passkeyId: string): Promise<PasskeyAttribute | undefined>;
17
+ export declare function setCurrentRegistrationOptions(user: UserModel, verified: VerifiedRegistrationResponse): Promise<void>;
18
+ export declare interface PasskeyAttribute {
19
+ id: string
20
+ cred_public_key: string
21
+ user_id: number
22
+ webauthn_user_id: string
23
+ counter: number
24
+ credential_type: string
25
+ device_type: string
26
+ backup_eligible: boolean
27
+ backup_status: boolean
28
+ transports?: string
29
+ created_at?: Date
30
+ last_used_at: string
31
+ }
32
+ declare type UserModel = InstanceType<typeof User>;
33
+ declare type PasskeyInsertable = Insertable<PasskeyAttribute>;
34
+ // Re-export WebAuthn functions from ts-auth
35
+ export {
36
+ generateRegistrationOptions,
37
+ generateAuthenticationOptions,
38
+ verifyRegistrationResponse,
39
+ verifyAuthenticationResponse,
40
+ // Browser-side functions (for client use)
41
+ startRegistration,
42
+ startAuthentication,
43
+ browserSupportsWebAuthn,
44
+ browserSupportsWebAuthnAutofill,
45
+ platformAuthenticatorIsAvailable,
46
+ } from '@stacksjs/ts-auth';
@@ -0,0 +1,10 @@
1
+ export declare function passwordResets(email: string): PasswordResetActions;
2
+ export declare interface PasswordResetResult {
3
+ success: boolean
4
+ message?: string
5
+ }
6
+ export declare interface PasswordResetActions {
7
+ sendEmail: () => Promise<void>
8
+ verifyToken: (token: string) => Promise<boolean>
9
+ resetPassword: (token: string, newPassword: string) => Promise<PasswordResetResult>
10
+ }
@@ -0,0 +1,33 @@
1
+ import { AuthorizationResponse } from './gate';
2
+ import type { UserModel as OrmUserModel } from '@stacksjs/orm';
3
+ /**
4
+ * Discover and register policies from app/Policies directory
5
+ */
6
+ export declare function discoverPolicies(): Promise<void>;
7
+ /**
8
+ * Register inline gates from Gates.ts
9
+ */
10
+ export declare function registerGates(): Promise<void>;
11
+ /**
12
+ * Initialize authorization system
13
+ */
14
+ export declare function initializeAuthorization(): Promise<void>;
15
+ // Use the row/instance shape from orm so policies operate on the
16
+ // authenticated user object, not the User class constructor.
17
+ declare type UserModel = OrmUserModel;
18
+ export declare abstract class BasePolicy<T = any> {
19
+ before?(user: UserModel | null, ability: string): boolean | null | Promise<boolean | null>;
20
+ viewAny?(user: UserModel | null): boolean | Promise<boolean> | AuthorizationResponse;
21
+ view?(user: UserModel | null, model: T): boolean | Promise<boolean> | AuthorizationResponse;
22
+ create?(user: UserModel | null): boolean | Promise<boolean> | AuthorizationResponse;
23
+ update?(user: UserModel | null, model: T): boolean | Promise<boolean> | AuthorizationResponse;
24
+ delete?(user: UserModel | null, model: T): boolean | Promise<boolean> | AuthorizationResponse;
25
+ restore?(user: UserModel | null, model: T): boolean | Promise<boolean> | AuthorizationResponse;
26
+ forceDelete?(user: UserModel | null, model: T): boolean | Promise<boolean> | AuthorizationResponse;
27
+ protected allow(message?: string): AuthorizationResponse;
28
+ protected deny(message?: string, code?: string): AuthorizationResponse;
29
+ protected denyIf(condition: boolean, message?: string): AuthorizationResponse | boolean;
30
+ protected denyUnless(condition: boolean, message?: string): AuthorizationResponse | boolean;
31
+ protected allowIf(condition: boolean, message?: string): AuthorizationResponse | boolean;
32
+ }
33
+ export { AuthorizationResponse };
@@ -0,0 +1,6 @@
1
+ export declare class RateLimiter {
2
+ static isRateLimited(email: string): boolean;
3
+ static recordFailedAttempt(email: string): void;
4
+ static resetAttempts(email: string): void;
5
+ static validateAttempt(email: string): void;
6
+ }