mulguard 1.1.2 → 1.1.4
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.
- package/dist/core/auth/oauth-providers.d.ts +175 -49
- package/dist/core/auth/oauth-state-store-redis.d.ts +25 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/mulguard/auth-handlers.d.ts +100 -0
- package/dist/core/mulguard/defaults.d.ts +58 -0
- package/dist/core/mulguard/index.d.ts +9 -0
- package/dist/core/mulguard/oauth-handler.d.ts +93 -0
- package/dist/core/mulguard/session-manager.d.ts +94 -0
- package/dist/core/security/index.d.ts +113 -9
- package/dist/core/security/validation.d.ts +231 -33
- package/dist/core/types/auth.d.ts +234 -75
- package/dist/core/types/errors.d.ts +174 -18
- package/dist/core/types/index.d.ts +397 -333
- package/dist/core/utils/logger.d.ts +112 -8
- package/dist/handlers/route.d.ts +59 -5
- package/dist/index/index.js +1 -1
- package/dist/index/index.mjs +1579 -1213
- package/dist/mulguard.d.ts +76 -1
- package/dist/server/helpers.d.ts +3 -3
- package/dist/server/utils.d.ts +3 -3
- package/package.json +1 -1
|
@@ -1,398 +1,462 @@
|
|
|
1
|
+
import { User, Session, AuthResult, SuccessfulAuthResult, FailedAuthResult, TwoFactorAuthResult, EmailCredentials, RegisterData, Verify2FAData } from './auth';
|
|
1
2
|
/**
|
|
2
|
-
* Core
|
|
3
|
-
*
|
|
3
|
+
* Core type definitions for Mulguard Authentication Library
|
|
4
|
+
*
|
|
5
|
+
* @module @mulguard/core/types
|
|
6
|
+
* @see {@link https://github.com/mulguard/mulguard} for documentation
|
|
4
7
|
*/
|
|
5
8
|
export * from './auth';
|
|
6
9
|
export * from './errors';
|
|
7
10
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
11
|
+
* Generic HTTP client interface for making API requests.
|
|
12
|
+
*
|
|
13
|
+
* @template TResponse - Response data type
|
|
14
|
+
* @template TRequest - Request data type (optional)
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const client: ApiClient = {
|
|
19
|
+
* get: async <T>(url: string) => ({ data: await fetch(url).then(r => r.json()) as T }),
|
|
20
|
+
* post: async <T>(url: string, data?: unknown) => ({ data: await fetch(url, { method: 'POST', body: JSON.stringify(data) }).then(r => r.json()) as T }),
|
|
21
|
+
* // ...
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
10
24
|
*/
|
|
11
25
|
export interface ApiClient {
|
|
12
|
-
|
|
13
|
-
|
|
26
|
+
/** GET request */
|
|
27
|
+
get: <TResponse = unknown>(url: string, config?: unknown) => Promise<{
|
|
28
|
+
data: TResponse;
|
|
14
29
|
}>;
|
|
15
|
-
|
|
16
|
-
|
|
30
|
+
/** POST request */
|
|
31
|
+
post: <TResponse = unknown, TRequest = unknown>(url: string, data?: TRequest, config?: unknown) => Promise<{
|
|
32
|
+
data: TResponse;
|
|
17
33
|
}>;
|
|
18
|
-
|
|
19
|
-
|
|
34
|
+
/** PUT request */
|
|
35
|
+
put: <TResponse = unknown, TRequest = unknown>(url: string, data?: TRequest, config?: unknown) => Promise<{
|
|
36
|
+
data: TResponse;
|
|
20
37
|
}>;
|
|
21
|
-
|
|
22
|
-
|
|
38
|
+
/** DELETE request */
|
|
39
|
+
delete: <TResponse = unknown>(url: string, config?: unknown) => Promise<{
|
|
40
|
+
data: TResponse;
|
|
23
41
|
}>;
|
|
24
42
|
}
|
|
25
43
|
/**
|
|
26
|
-
*
|
|
44
|
+
* Authentication provider type.
|
|
45
|
+
*/
|
|
46
|
+
export type AuthProvider = 'email' | 'oauth' | 'passkey';
|
|
47
|
+
/**
|
|
48
|
+
* Remembered user information for account picker functionality.
|
|
49
|
+
*
|
|
50
|
+
* @property userId - Unique user identifier
|
|
51
|
+
* @property email - User email address
|
|
52
|
+
* @property name - User display name
|
|
53
|
+
* @property avatar - Optional avatar URL
|
|
54
|
+
* @property provider - Authentication provider used
|
|
55
|
+
* @property lastLoginAt - Timestamp of last login
|
|
27
56
|
*/
|
|
28
57
|
export interface RememberedUser {
|
|
29
|
-
userId: string;
|
|
30
|
-
email: string;
|
|
31
|
-
name: string;
|
|
32
|
-
avatar?: string;
|
|
33
|
-
provider:
|
|
34
|
-
lastLoginAt: Date;
|
|
58
|
+
readonly userId: string;
|
|
59
|
+
readonly email: string;
|
|
60
|
+
readonly name: string;
|
|
61
|
+
readonly avatar?: string;
|
|
62
|
+
readonly provider: AuthProvider;
|
|
63
|
+
readonly lastLoginAt: Date;
|
|
35
64
|
}
|
|
36
65
|
/**
|
|
37
|
-
* OAuth
|
|
38
|
-
*
|
|
66
|
+
* OAuth provider configuration.
|
|
67
|
+
*
|
|
68
|
+
* @property clientId - OAuth client identifier (required)
|
|
69
|
+
* @property clientSecret - OAuth client secret (server-side only, optional)
|
|
70
|
+
* @property redirectUri - Custom redirect URI (auto-generated if not provided)
|
|
71
|
+
* @property scopes - OAuth scopes (defaults provided per provider)
|
|
72
|
+
* @property params - Additional OAuth parameters
|
|
39
73
|
*/
|
|
40
74
|
export interface OAuthProviderConfig {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
redirectUri?: string;
|
|
47
|
-
/** Custom scopes (optional, defaults provided) */
|
|
48
|
-
scopes?: string[];
|
|
49
|
-
/** Additional parameters */
|
|
50
|
-
params?: Record<string, string>;
|
|
75
|
+
readonly clientId: string;
|
|
76
|
+
readonly clientSecret?: string;
|
|
77
|
+
readonly redirectUri?: string;
|
|
78
|
+
readonly scopes?: readonly string[];
|
|
79
|
+
readonly params?: Readonly<Record<string, string>>;
|
|
51
80
|
}
|
|
52
81
|
/**
|
|
53
|
-
* OAuth
|
|
54
|
-
*
|
|
82
|
+
* OAuth providers configuration map.
|
|
83
|
+
*
|
|
84
|
+
* Supports built-in providers (google, github, apple, facebook) and custom providers.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const providers: OAuthProvidersConfig = {
|
|
89
|
+
* google: { clientId: '...', clientSecret: '...' },
|
|
90
|
+
* custom: { clientId: '...', scopes: ['read', 'write'] }
|
|
91
|
+
* }
|
|
92
|
+
* ```
|
|
55
93
|
*/
|
|
56
94
|
export interface OAuthProvidersConfig {
|
|
57
|
-
google?: OAuthProviderConfig;
|
|
58
|
-
github?: OAuthProviderConfig;
|
|
59
|
-
apple?: OAuthProviderConfig;
|
|
60
|
-
facebook?: OAuthProviderConfig;
|
|
61
|
-
[key: string]: OAuthProviderConfig | undefined;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Main configuration for Mulguard
|
|
65
|
-
* User provides custom logic for each authentication method
|
|
66
|
-
*/
|
|
67
|
-
export interface MulguardConfig {
|
|
68
|
-
/** Session configuration */
|
|
69
|
-
session?: SessionConfig;
|
|
70
|
-
/** Custom authentication logic - user writes their own implementation */
|
|
71
|
-
actions: AuthActions;
|
|
72
|
-
/** Callbacks for lifecycle events */
|
|
73
|
-
callbacks?: CallbacksConfig;
|
|
74
|
-
/** Security configuration */
|
|
75
|
-
security?: SecurityConfig;
|
|
76
|
-
/** Token refresh configuration */
|
|
77
|
-
tokenRefresh?: import('../client/token-refresh-manager').TokenRefreshConfig;
|
|
78
|
-
/** ✅ NEW: OAuth providers configuration (auth.js-like) */
|
|
79
|
-
providers?: {
|
|
80
|
-
oauth?: OAuthProvidersConfig;
|
|
81
|
-
};
|
|
82
|
-
/** ✅ NEW: OAuth state store (for production, use Redis/database-backed store) */
|
|
83
|
-
oauthStateStore?: import('../auth/oauth-state-store').OAuthStateStore;
|
|
84
|
-
/** ✅ NEW: Session cache TTL in milliseconds (default: 5000) */
|
|
85
|
-
sessionCacheTtl?: number;
|
|
95
|
+
readonly google?: OAuthProviderConfig;
|
|
96
|
+
readonly github?: OAuthProviderConfig;
|
|
97
|
+
readonly apple?: OAuthProviderConfig;
|
|
98
|
+
readonly facebook?: OAuthProviderConfig;
|
|
99
|
+
readonly [key: string]: OAuthProviderConfig | undefined;
|
|
86
100
|
}
|
|
87
101
|
/**
|
|
88
|
-
*
|
|
102
|
+
* OAuth token response from provider.
|
|
103
|
+
*
|
|
104
|
+
* @property access_token - Access token (required)
|
|
105
|
+
* @property refresh_token - Refresh token (optional)
|
|
106
|
+
* @property expires_in - Token expiration in seconds (optional)
|
|
107
|
+
* @property token_type - Token type, typically 'Bearer' (optional)
|
|
108
|
+
* @property id_token - ID token for OpenID Connect (optional)
|
|
109
|
+
* @property scope - Granted scopes (optional)
|
|
89
110
|
*/
|
|
90
|
-
export
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
email?: string;
|
|
98
|
-
code?: string;
|
|
99
|
-
};
|
|
111
|
+
export interface OAuthTokens {
|
|
112
|
+
readonly access_token: string;
|
|
113
|
+
readonly refresh_token?: string;
|
|
114
|
+
readonly expires_in?: number;
|
|
115
|
+
readonly token_type?: string;
|
|
116
|
+
readonly id_token?: string;
|
|
117
|
+
readonly scope?: string;
|
|
100
118
|
}
|
|
101
119
|
/**
|
|
102
|
-
*
|
|
103
|
-
*
|
|
120
|
+
* Enhanced OAuth user information with tokens and provider metadata.
|
|
121
|
+
*
|
|
122
|
+
* This interface extends basic user info with OAuth-specific data required for
|
|
123
|
+
* backend API integration and advanced use cases.
|
|
124
|
+
*
|
|
125
|
+
* @property id - User ID from OAuth provider
|
|
126
|
+
* @property email - User email from OAuth provider
|
|
127
|
+
* @property name - User display name
|
|
128
|
+
* @property avatar - User avatar URL (optional)
|
|
129
|
+
* @property emailVerified - Email verification status (optional)
|
|
130
|
+
* @property provider - OAuth provider identifier (e.g., 'google', 'github')
|
|
131
|
+
* @property accessToken - OAuth access token (required for backend API)
|
|
132
|
+
* @property refreshToken - OAuth refresh token (optional)
|
|
133
|
+
* @property tokens - Complete OAuth tokens object
|
|
134
|
+
* @property rawProfile - Raw profile data from provider (for advanced use)
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* callbacks: {
|
|
139
|
+
* onOAuthUser: async (userInfo) => {
|
|
140
|
+
* // userInfo.accessToken available for backend API calls
|
|
141
|
+
* // userInfo.rawProfile available for provider-specific data
|
|
142
|
+
* return await createOrUpdateUser(userInfo)
|
|
143
|
+
* }
|
|
144
|
+
* }
|
|
145
|
+
* ```
|
|
104
146
|
*/
|
|
105
|
-
export interface
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
* Returns authorization URL and state
|
|
118
|
-
*/
|
|
119
|
-
oauth?: (provider: string) => Promise<{
|
|
120
|
-
url: string;
|
|
121
|
-
state: string;
|
|
122
|
-
}>;
|
|
123
|
-
/**
|
|
124
|
-
* PassKey/WebAuthn sign in
|
|
125
|
-
*/
|
|
126
|
-
passkey?: (options?: {
|
|
127
|
-
userId?: string;
|
|
128
|
-
}) => Promise<AuthResult>;
|
|
129
|
-
/**
|
|
130
|
-
* OTP sign in
|
|
131
|
-
*/
|
|
132
|
-
otp?: (email: string, code?: string) => Promise<AuthResult>;
|
|
133
|
-
};
|
|
134
|
-
/**
|
|
135
|
-
* Sign up new user
|
|
136
|
-
* User implements custom logic here
|
|
137
|
-
*/
|
|
138
|
-
signUp?: (data: RegisterData) => Promise<AuthResult>;
|
|
139
|
-
/**
|
|
140
|
-
* Sign out current session
|
|
141
|
-
* User implements custom logic here
|
|
142
|
-
*/
|
|
143
|
-
signOut?: () => Promise<{
|
|
144
|
-
success: boolean;
|
|
145
|
-
error?: string;
|
|
146
|
-
}>;
|
|
147
|
-
/**
|
|
148
|
-
* Request password reset
|
|
149
|
-
* User implements custom logic here
|
|
150
|
-
*/
|
|
151
|
-
resetPassword?: (email: string) => Promise<{
|
|
152
|
-
success: boolean;
|
|
153
|
-
error?: string;
|
|
154
|
-
}>;
|
|
155
|
-
/**
|
|
156
|
-
* Verify email address
|
|
157
|
-
* User implements custom logic here
|
|
158
|
-
*/
|
|
159
|
-
verifyEmail?: (token: string) => Promise<{
|
|
160
|
-
success: boolean;
|
|
161
|
-
error?: string;
|
|
162
|
-
}>;
|
|
163
|
-
/**
|
|
164
|
-
* Get current session
|
|
165
|
-
* User implements custom logic here
|
|
166
|
-
*/
|
|
167
|
-
getSession?: () => Promise<Session | null>;
|
|
168
|
-
/**
|
|
169
|
-
* Refresh session
|
|
170
|
-
* User implements custom logic here
|
|
171
|
-
*/
|
|
172
|
-
refreshSession?: () => Promise<Session | null>;
|
|
173
|
-
/**
|
|
174
|
-
* OAuth callback handler
|
|
175
|
-
* User implements custom logic here
|
|
176
|
-
*/
|
|
177
|
-
oauthCallback?: (provider: string, code: string, state: string) => Promise<AuthResult>;
|
|
178
|
-
/**
|
|
179
|
-
* PassKey methods
|
|
180
|
-
*/
|
|
181
|
-
passkey?: {
|
|
182
|
-
register?: (options?: {
|
|
183
|
-
name?: string;
|
|
184
|
-
userId?: string;
|
|
185
|
-
}) => Promise<{
|
|
186
|
-
success: boolean;
|
|
187
|
-
passkeyId?: string;
|
|
188
|
-
error?: string;
|
|
189
|
-
}>;
|
|
190
|
-
authenticate?: (options?: {
|
|
191
|
-
userId?: string;
|
|
192
|
-
}) => Promise<AuthResult>;
|
|
193
|
-
list?: () => Promise<Array<{
|
|
194
|
-
id: string;
|
|
195
|
-
name: string;
|
|
196
|
-
createdAt: Date;
|
|
197
|
-
lastUsedAt?: Date;
|
|
198
|
-
}>>;
|
|
199
|
-
remove?: (passKeyId: string) => Promise<{
|
|
200
|
-
success: boolean;
|
|
201
|
-
error?: string;
|
|
202
|
-
}>;
|
|
203
|
-
};
|
|
204
|
-
/**
|
|
205
|
-
* Two-Factor Authentication methods
|
|
206
|
-
*/
|
|
207
|
-
twoFactor?: {
|
|
208
|
-
enable?: () => Promise<{
|
|
209
|
-
success: boolean;
|
|
210
|
-
qrCode?: string;
|
|
211
|
-
secret?: string;
|
|
212
|
-
error?: string;
|
|
213
|
-
}>;
|
|
214
|
-
verify?: (code: string) => Promise<{
|
|
215
|
-
success: boolean;
|
|
216
|
-
backupCodes?: string[];
|
|
217
|
-
error?: string;
|
|
218
|
-
}>;
|
|
219
|
-
disable?: () => Promise<{
|
|
220
|
-
success: boolean;
|
|
221
|
-
error?: string;
|
|
222
|
-
}>;
|
|
223
|
-
generateBackupCodes?: () => Promise<{
|
|
224
|
-
success: boolean;
|
|
225
|
-
backupCodes?: string[];
|
|
226
|
-
error?: string;
|
|
227
|
-
}>;
|
|
228
|
-
isEnabled?: () => Promise<boolean>;
|
|
229
|
-
/**
|
|
230
|
-
* Verify 2FA code after initial sign in
|
|
231
|
-
* Used when signIn returns requires2FA: true
|
|
232
|
-
*/
|
|
233
|
-
verify2FA?: (data: import('./auth').Verify2FAData) => Promise<import('./auth').AuthResult>;
|
|
234
|
-
};
|
|
235
|
-
/**
|
|
236
|
-
* Verify 2FA code after initial sign in (legacy - use twoFactor.verify2FA instead)
|
|
237
|
-
* Used when signIn returns requires2FA: true
|
|
238
|
-
*/
|
|
239
|
-
verify2FA?: (data: import('./auth').Verify2FAData) => Promise<import('./auth').AuthResult>;
|
|
147
|
+
export interface OAuthUserInfo {
|
|
148
|
+
readonly id: string;
|
|
149
|
+
readonly email: string;
|
|
150
|
+
readonly name: string;
|
|
151
|
+
readonly avatar?: string;
|
|
152
|
+
readonly emailVerified?: boolean;
|
|
153
|
+
readonly provider: string;
|
|
154
|
+
readonly accessToken: string;
|
|
155
|
+
readonly refreshToken?: string;
|
|
156
|
+
readonly tokens: OAuthTokens;
|
|
157
|
+
readonly rawProfile?: Readonly<Record<string, unknown>>;
|
|
158
|
+
readonly [key: string]: unknown;
|
|
240
159
|
}
|
|
241
160
|
/**
|
|
242
|
-
* Session configuration
|
|
161
|
+
* Session cookie configuration.
|
|
162
|
+
*
|
|
163
|
+
* @property cookieName - Cookie name (default: '__mulguard_session')
|
|
164
|
+
* @property expiresIn - Session expiration in seconds (default: 7 days)
|
|
165
|
+
* @property httpOnly - HttpOnly flag (default: true)
|
|
166
|
+
* @property secure - Secure flag (default: true in production)
|
|
167
|
+
* @property sameSite - SameSite policy (default: 'lax')
|
|
168
|
+
* @property path - Cookie path (default: '/')
|
|
169
|
+
* @property domain - Cookie domain (optional)
|
|
170
|
+
* @property cacheTtl - Session cache TTL in milliseconds (default: 5000)
|
|
243
171
|
*/
|
|
244
172
|
export interface SessionConfig {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
/** SameSite policy (default: 'lax') */
|
|
254
|
-
sameSite?: 'strict' | 'lax' | 'none';
|
|
255
|
-
/** Cookie path (default: '/') */
|
|
256
|
-
path?: string;
|
|
257
|
-
/** Cookie domain (optional) */
|
|
258
|
-
domain?: string;
|
|
259
|
-
/** Session cache TTL in milliseconds (default: 5000) */
|
|
260
|
-
cacheTtl?: number;
|
|
173
|
+
readonly cookieName?: string;
|
|
174
|
+
readonly expiresIn?: number;
|
|
175
|
+
readonly httpOnly?: boolean;
|
|
176
|
+
readonly secure?: boolean;
|
|
177
|
+
readonly sameSite?: 'strict' | 'lax' | 'none';
|
|
178
|
+
readonly path?: string;
|
|
179
|
+
readonly domain?: string;
|
|
180
|
+
readonly cacheTtl?: number;
|
|
261
181
|
}
|
|
262
182
|
/**
|
|
263
|
-
* Security configuration
|
|
183
|
+
* Security configuration options.
|
|
184
|
+
*
|
|
185
|
+
* @property csrfProtection - Enable CSRF protection (default: true)
|
|
186
|
+
* @property rateLimiting - Enable rate limiting (default: true)
|
|
187
|
+
* @property requireHttps - Require HTTPS (default: true in production)
|
|
188
|
+
* @property allowedOrigins - Allowed origins for CORS
|
|
264
189
|
*/
|
|
265
190
|
export interface SecurityConfig {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
/** Require HTTPS (default: true in production) */
|
|
271
|
-
requireHttps?: boolean;
|
|
272
|
-
/** Allowed origins for CORS */
|
|
273
|
-
allowedOrigins?: string[];
|
|
191
|
+
readonly csrfProtection?: boolean;
|
|
192
|
+
readonly rateLimiting?: boolean;
|
|
193
|
+
readonly requireHttps?: boolean;
|
|
194
|
+
readonly allowedOrigins?: readonly string[];
|
|
274
195
|
}
|
|
275
196
|
/**
|
|
276
|
-
* OAuth
|
|
197
|
+
* OAuth provider identifier.
|
|
277
198
|
*/
|
|
278
|
-
export
|
|
279
|
-
access_token: string;
|
|
280
|
-
refresh_token?: string;
|
|
281
|
-
expires_in?: number;
|
|
282
|
-
token_type?: string;
|
|
283
|
-
id_token?: string;
|
|
284
|
-
scope?: string;
|
|
285
|
-
}
|
|
199
|
+
export type OAuthProviderId = 'google' | 'github' | 'apple' | 'facebook' | string;
|
|
286
200
|
/**
|
|
287
|
-
*
|
|
288
|
-
* Enhanced with tokens and provider information for maximum flexibility
|
|
201
|
+
* Sign-in provider type.
|
|
289
202
|
*/
|
|
290
|
-
export
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
tokens: OAuthTokens;
|
|
309
|
-
/** ✅ NEW: Raw profile data from OAuth provider (for advanced use cases) */
|
|
310
|
-
rawProfile?: Record<string, unknown>;
|
|
311
|
-
/** ✅ NEW: Additional provider-specific fields */
|
|
312
|
-
[key: string]: unknown;
|
|
203
|
+
export type SignInProvider = OAuthProviderId | 'credentials' | 'passkey' | 'otp';
|
|
204
|
+
/**
|
|
205
|
+
* Sign-in options for unified interface.
|
|
206
|
+
*
|
|
207
|
+
* @property provider - Authentication provider
|
|
208
|
+
* @property credentials - Email/password credentials (for 'credentials' provider)
|
|
209
|
+
* @property formData - Form data (alternative to credentials)
|
|
210
|
+
* @property options - Additional options (for 'otp' or 'passkey' providers)
|
|
211
|
+
*/
|
|
212
|
+
export interface SignInOptions {
|
|
213
|
+
readonly provider: SignInProvider;
|
|
214
|
+
readonly credentials?: Readonly<EmailCredentials>;
|
|
215
|
+
readonly formData?: FormData;
|
|
216
|
+
readonly options?: Readonly<{
|
|
217
|
+
userId?: string;
|
|
218
|
+
email?: string;
|
|
219
|
+
code?: string;
|
|
220
|
+
}>;
|
|
313
221
|
}
|
|
314
222
|
/**
|
|
315
|
-
*
|
|
223
|
+
* Lifecycle callbacks configuration.
|
|
224
|
+
*
|
|
225
|
+
* All callbacks are optional and can be used to hook into authentication events.
|
|
226
|
+
*
|
|
227
|
+
* @property onSignIn - Called after successful sign-in
|
|
228
|
+
* @property onSignOut - Called after sign-out
|
|
229
|
+
* @property onSessionUpdate - Called when session is updated (can modify session)
|
|
230
|
+
* @property onError - Called on authentication errors
|
|
231
|
+
* @property onTokenRefresh - Called when tokens are refreshed
|
|
232
|
+
* @property onSessionExpired - Called when session expires
|
|
233
|
+
* @property onOAuthUser - Called when OAuth user is received (for user creation/lookup)
|
|
316
234
|
*/
|
|
317
235
|
export interface CallbacksConfig {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
onError?: (error: Error, context?: string) => Promise<void> | void;
|
|
326
|
-
/** Called when token is refreshed */
|
|
327
|
-
onTokenRefresh?: (oldSession: Session, newSession: Session) => Promise<void> | void;
|
|
328
|
-
/** Called when session expires */
|
|
329
|
-
onSessionExpired?: (session: Session) => Promise<void> | void;
|
|
330
|
-
/** ✅ NEW: Called when OAuth user is received (for auto-generated OAuth callback) */
|
|
331
|
-
onOAuthUser?: (userInfo: OAuthUserInfo, provider: string) => Promise<User>;
|
|
236
|
+
readonly onSignIn?: (user: User, session: Session) => Promise<void> | void;
|
|
237
|
+
readonly onSignOut?: (user: User) => Promise<void> | void;
|
|
238
|
+
readonly onSessionUpdate?: (session: Session) => Promise<Session> | Session;
|
|
239
|
+
readonly onError?: (error: Error, context?: string) => Promise<void> | void;
|
|
240
|
+
readonly onTokenRefresh?: (oldSession: Session, newSession: Session) => Promise<void> | void;
|
|
241
|
+
readonly onSessionExpired?: (session: Session) => Promise<void> | void;
|
|
242
|
+
readonly onOAuthUser?: (userInfo: OAuthUserInfo, provider: string) => Promise<User>;
|
|
332
243
|
}
|
|
333
244
|
/**
|
|
334
|
-
*
|
|
245
|
+
* Request context for Server Actions.
|
|
246
|
+
*
|
|
247
|
+
* Provides access to request metadata for authentication operations.
|
|
248
|
+
*
|
|
249
|
+
* @property headers - Request headers
|
|
250
|
+
* @property cookies - Request cookies map
|
|
251
|
+
* @property ip - Client IP address (optional)
|
|
252
|
+
* @property userAgent - User agent string (optional)
|
|
335
253
|
*/
|
|
336
|
-
export interface
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
roles?: string[];
|
|
342
|
-
emailVerified?: boolean;
|
|
343
|
-
[key: string]: unknown;
|
|
254
|
+
export interface RequestContext {
|
|
255
|
+
readonly headers: Headers;
|
|
256
|
+
readonly cookies: ReadonlyMap<string, string>;
|
|
257
|
+
readonly ip?: string;
|
|
258
|
+
readonly userAgent?: string;
|
|
344
259
|
}
|
|
345
260
|
/**
|
|
346
|
-
*
|
|
261
|
+
* Main Mulguard configuration interface.
|
|
262
|
+
*
|
|
263
|
+
* @template TUser - User type (extends base User)
|
|
264
|
+
* @template TSession - Session type (extends base Session)
|
|
265
|
+
*
|
|
266
|
+
* @property session - Session configuration
|
|
267
|
+
* @property actions - Custom authentication actions (required)
|
|
268
|
+
* @property callbacks - Lifecycle callbacks (optional)
|
|
269
|
+
* @property security - Security configuration (optional)
|
|
270
|
+
* @property tokenRefresh - Token refresh configuration (optional)
|
|
271
|
+
* @property providers - OAuth providers configuration (optional)
|
|
272
|
+
* @property oauthStateStore - OAuth state store (optional, uses in-memory by default)
|
|
273
|
+
* @property sessionCacheTtl - Session cache TTL in milliseconds (optional)
|
|
347
274
|
*/
|
|
348
|
-
export interface Session {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
275
|
+
export interface MulguardConfig<TUser extends User = User, TSession extends Session<TUser> = Session<TUser>> {
|
|
276
|
+
readonly session?: SessionConfig;
|
|
277
|
+
readonly actions: AuthActions<TUser, TSession>;
|
|
278
|
+
readonly callbacks?: CallbacksConfig;
|
|
279
|
+
readonly security?: SecurityConfig;
|
|
280
|
+
readonly tokenRefresh?: import('../client/token-refresh-manager').TokenRefreshConfig;
|
|
281
|
+
readonly providers?: {
|
|
282
|
+
readonly oauth?: OAuthProvidersConfig;
|
|
283
|
+
};
|
|
284
|
+
readonly oauthStateStore?: import('../auth/oauth-state-store').OAuthStateStore;
|
|
285
|
+
readonly sessionCacheTtl?: number;
|
|
352
286
|
}
|
|
287
|
+
export type { User, Session, AuthResult, SuccessfulAuthResult, FailedAuthResult, TwoFactorAuthResult, EmailCredentials, RegisterData, Verify2FAData, };
|
|
288
|
+
export { isAuthSuccess, isAuthFailure, isTwoFactorRequired } from './auth';
|
|
353
289
|
/**
|
|
354
|
-
*
|
|
290
|
+
* Custom authentication actions interface.
|
|
291
|
+
*
|
|
292
|
+
* Users implement these actions to provide custom authentication logic.
|
|
293
|
+
* All actions are Server Actions that run on the server.
|
|
294
|
+
*
|
|
295
|
+
* @template TUser - User type
|
|
296
|
+
* @template TSession - Session type
|
|
355
297
|
*/
|
|
356
|
-
export interface
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
298
|
+
export interface AuthActions<TUser extends User = User, TSession extends Session<TUser> = Session<TUser>> {
|
|
299
|
+
readonly signIn: SignInActions<TUser, TSession>;
|
|
300
|
+
readonly signUp?: (data: RegisterData) => Promise<AuthResult<TUser, TSession>>;
|
|
301
|
+
readonly signOut?: () => Promise<{
|
|
302
|
+
success: boolean;
|
|
303
|
+
error?: string;
|
|
304
|
+
}>;
|
|
305
|
+
readonly resetPassword?: (email: string) => Promise<{
|
|
306
|
+
success: boolean;
|
|
307
|
+
error?: string;
|
|
308
|
+
}>;
|
|
309
|
+
readonly verifyEmail?: (token: string) => Promise<{
|
|
310
|
+
success: boolean;
|
|
311
|
+
error?: string;
|
|
312
|
+
}>;
|
|
313
|
+
readonly getSession?: () => Promise<TSession | null>;
|
|
314
|
+
readonly refreshSession?: () => Promise<TSession | null>;
|
|
315
|
+
readonly oauthCallback?: (provider: string, code: string, state: string) => Promise<AuthResult<TUser, TSession>>;
|
|
316
|
+
readonly passkey?: PasskeyActions<TUser, TSession>;
|
|
317
|
+
readonly twoFactor?: TwoFactorActions<TUser, TSession>;
|
|
318
|
+
readonly verify2FA?: (data: Verify2FAData) => Promise<AuthResult<TUser, TSession>>;
|
|
369
319
|
}
|
|
370
320
|
/**
|
|
371
|
-
*
|
|
321
|
+
* Sign-in actions interface.
|
|
322
|
+
*
|
|
323
|
+
* @template TUser - User type
|
|
324
|
+
* @template TSession - Session type
|
|
372
325
|
*/
|
|
373
|
-
export interface
|
|
374
|
-
email:
|
|
375
|
-
|
|
326
|
+
export interface SignInActions<TUser extends User = User, TSession extends Session<TUser> = Session<TUser>> {
|
|
327
|
+
readonly email: (credentials: EmailCredentials) => Promise<AuthResult<TUser, TSession>>;
|
|
328
|
+
readonly oauth?: (provider: string) => Promise<{
|
|
329
|
+
url: string;
|
|
330
|
+
state: string;
|
|
331
|
+
}>;
|
|
332
|
+
readonly passkey?: (options?: {
|
|
333
|
+
userId?: string;
|
|
334
|
+
}) => Promise<AuthResult<TUser, TSession>>;
|
|
335
|
+
readonly otp?: (email: string, code?: string) => Promise<AuthResult<TUser, TSession>>;
|
|
376
336
|
}
|
|
377
337
|
/**
|
|
378
|
-
*
|
|
338
|
+
* Passkey actions interface.
|
|
339
|
+
*
|
|
340
|
+
* @template TUser - User type
|
|
341
|
+
* @template TSession - Session type
|
|
379
342
|
*/
|
|
380
|
-
export interface
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
343
|
+
export interface PasskeyActions<TUser extends User = User, TSession extends Session<TUser> = Session<TUser>> {
|
|
344
|
+
readonly register?: (options?: {
|
|
345
|
+
name?: string;
|
|
346
|
+
userId?: string;
|
|
347
|
+
}) => Promise<{
|
|
348
|
+
success: boolean;
|
|
349
|
+
passkeyId?: string;
|
|
350
|
+
error?: string;
|
|
351
|
+
}>;
|
|
352
|
+
readonly authenticate?: (options?: {
|
|
353
|
+
userId?: string;
|
|
354
|
+
}) => Promise<AuthResult<TUser, TSession>>;
|
|
355
|
+
readonly list?: () => Promise<ReadonlyArray<{
|
|
356
|
+
id: string;
|
|
357
|
+
name: string;
|
|
358
|
+
createdAt: Date;
|
|
359
|
+
lastUsedAt?: Date;
|
|
360
|
+
}>>;
|
|
361
|
+
readonly remove?: (passKeyId: string) => Promise<{
|
|
362
|
+
success: boolean;
|
|
363
|
+
error?: string;
|
|
364
|
+
}>;
|
|
385
365
|
}
|
|
386
366
|
/**
|
|
387
|
-
*
|
|
367
|
+
* Two-factor authentication actions interface.
|
|
368
|
+
*
|
|
369
|
+
* @template TUser - User type
|
|
370
|
+
* @template TSession - Session type
|
|
388
371
|
*/
|
|
389
|
-
export interface
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
372
|
+
export interface TwoFactorActions<TUser extends User = User, TSession extends Session<TUser> = Session<TUser>> {
|
|
373
|
+
readonly enable?: () => Promise<{
|
|
374
|
+
success: boolean;
|
|
375
|
+
qrCode?: string;
|
|
376
|
+
secret?: string;
|
|
377
|
+
error?: string;
|
|
378
|
+
}>;
|
|
379
|
+
readonly verify?: (code: string) => Promise<{
|
|
380
|
+
success: boolean;
|
|
381
|
+
backupCodes?: string[];
|
|
382
|
+
error?: string;
|
|
383
|
+
}>;
|
|
384
|
+
readonly disable?: () => Promise<{
|
|
385
|
+
success: boolean;
|
|
386
|
+
error?: string;
|
|
387
|
+
}>;
|
|
388
|
+
readonly generateBackupCodes?: () => Promise<{
|
|
389
|
+
success: boolean;
|
|
390
|
+
backupCodes?: string[];
|
|
391
|
+
error?: string;
|
|
392
|
+
}>;
|
|
393
|
+
readonly isEnabled?: () => Promise<boolean>;
|
|
394
|
+
readonly verify2FA?: (data: Verify2FAData) => Promise<AuthResult<TUser, TSession>>;
|
|
398
395
|
}
|
|
396
|
+
/**
|
|
397
|
+
* Type predicate to check if a value is a valid User object.
|
|
398
|
+
*
|
|
399
|
+
* @param value - Value to check
|
|
400
|
+
* @returns True if value is a valid User
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
* ```typescript
|
|
404
|
+
* if (isUser(data)) {
|
|
405
|
+
* // TypeScript knows data is User here
|
|
406
|
+
* console.log(data.email)
|
|
407
|
+
* }
|
|
408
|
+
* ```
|
|
409
|
+
*/
|
|
410
|
+
export declare function isUser(value: unknown): value is User;
|
|
411
|
+
/**
|
|
412
|
+
* Type predicate to check if a value is a valid Session object.
|
|
413
|
+
*
|
|
414
|
+
* @template TUser - User type
|
|
415
|
+
* @param value - Value to check
|
|
416
|
+
* @returns True if value is a valid Session
|
|
417
|
+
*
|
|
418
|
+
* @example
|
|
419
|
+
* ```typescript
|
|
420
|
+
* if (isSession(data)) {
|
|
421
|
+
* // TypeScript knows data is Session here
|
|
422
|
+
* console.log(data.user.email)
|
|
423
|
+
* }
|
|
424
|
+
* ```
|
|
425
|
+
*/
|
|
426
|
+
export declare function isSession<TUser extends User = User>(value: unknown): value is Session<TUser>;
|
|
427
|
+
/**
|
|
428
|
+
* TODO: Performance
|
|
429
|
+
* - [ ] Add type-level optimizations for large union types
|
|
430
|
+
* - [ ] Consider using branded types for IDs to prevent mixing
|
|
431
|
+
* - [ ] Add type-level validation for configuration objects
|
|
432
|
+
* - [ ] Implement type-safe builder pattern for complex configurations
|
|
433
|
+
*
|
|
434
|
+
* TODO: Features
|
|
435
|
+
* - [ ] Add conditional types for provider-specific OAuth configs
|
|
436
|
+
* - [ ] Implement discriminated unions for AuthResult variants
|
|
437
|
+
* - [ ] Add type-level session expiration checking
|
|
438
|
+
* - [ ] Create type-safe middleware chain types
|
|
439
|
+
* - [ ] Add generic constraints for custom User/Session extensions
|
|
440
|
+
*
|
|
441
|
+
* TODO: Type Safety
|
|
442
|
+
* - [ ] Add branded types for sensitive data (tokens, passwords)
|
|
443
|
+
* - [ ] Implement type-level validation for email formats
|
|
444
|
+
* - [ ] Add type guards for all public interfaces
|
|
445
|
+
* - [ ] Create type-safe error handling with exhaustiveness checking
|
|
446
|
+
*
|
|
447
|
+
* TODO: Testing
|
|
448
|
+
* - [ ] Add type-level tests using ts-expect
|
|
449
|
+
* - [ ] Test type inference in various scenarios
|
|
450
|
+
* - [ ] Verify type narrowing with type predicates
|
|
451
|
+
* - [ ] Test generic constraints and conditional types
|
|
452
|
+
*
|
|
453
|
+
* TODO: Documentation
|
|
454
|
+
* - [ ] Add more JSDoc examples for complex types
|
|
455
|
+
* - [ ] Document type-level patterns and best practices
|
|
456
|
+
* - [ ] Create type usage guides
|
|
457
|
+
*
|
|
458
|
+
* TODO: Limitations
|
|
459
|
+
* - [ ] Type inference may be limited with very complex generic chains
|
|
460
|
+
* - [ ] Branded types add runtime overhead (consider compile-time only)
|
|
461
|
+
* - [ ] Deep readonly types may impact performance with large objects
|
|
462
|
+
*/
|