@nauth-toolkit/core 0.1.0 → 0.1.3

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.
Files changed (184) hide show
  1. package/LICENSE +90 -0
  2. package/README.md +30 -0
  3. package/package.json +7 -2
  4. package/jest.config.js +0 -15
  5. package/jest.setup.ts +0 -6
  6. package/src/adapters/database-columns.ts +0 -165
  7. package/src/adapters/express.adapter.ts +0 -385
  8. package/src/adapters/fastify.adapter.ts +0 -416
  9. package/src/adapters/index.ts +0 -16
  10. package/src/adapters/storage.factory.ts +0 -143
  11. package/src/bootstrap.ts +0 -374
  12. package/src/dto/auth-challenge.dto.ts +0 -231
  13. package/src/dto/auth-response.dto.ts +0 -253
  14. package/src/dto/challenge-response.dto.ts +0 -234
  15. package/src/dto/change-password-request.dto.ts +0 -50
  16. package/src/dto/change-password-response.dto.ts +0 -29
  17. package/src/dto/change-password.dto.ts +0 -57
  18. package/src/dto/error-response.dto.ts +0 -136
  19. package/src/dto/get-available-methods.dto.ts +0 -55
  20. package/src/dto/get-challenge-data-response.dto.ts +0 -28
  21. package/src/dto/get-challenge-data.dto.ts +0 -69
  22. package/src/dto/get-client-info.dto.ts +0 -104
  23. package/src/dto/get-device-token-response.dto.ts +0 -25
  24. package/src/dto/get-events-by-type.dto.ts +0 -76
  25. package/src/dto/get-ip-address-response.dto.ts +0 -24
  26. package/src/dto/get-mfa-status.dto.ts +0 -94
  27. package/src/dto/get-risk-assessment-history.dto.ts +0 -39
  28. package/src/dto/get-session-id-response.dto.ts +0 -25
  29. package/src/dto/get-setup-data-response.dto.ts +0 -31
  30. package/src/dto/get-setup-data.dto.ts +0 -75
  31. package/src/dto/get-suspicious-activity.dto.ts +0 -42
  32. package/src/dto/get-user-agent-response.dto.ts +0 -23
  33. package/src/dto/get-user-auth-history.dto.ts +0 -95
  34. package/src/dto/get-user-by-email.dto.ts +0 -61
  35. package/src/dto/get-user-by-id.dto.ts +0 -46
  36. package/src/dto/get-user-devices.dto.ts +0 -53
  37. package/src/dto/get-user-response.dto.ts +0 -17
  38. package/src/dto/has-provider.dto.ts +0 -56
  39. package/src/dto/index.ts +0 -57
  40. package/src/dto/is-trusted-device-response.dto.ts +0 -34
  41. package/src/dto/list-providers-response.dto.ts +0 -23
  42. package/src/dto/login.dto.ts +0 -95
  43. package/src/dto/logout-all-response.dto.ts +0 -24
  44. package/src/dto/logout-all.dto.ts +0 -65
  45. package/src/dto/logout-response.dto.ts +0 -25
  46. package/src/dto/logout.dto.ts +0 -64
  47. package/src/dto/refresh-token.dto.ts +0 -36
  48. package/src/dto/remove-devices.dto.ts +0 -85
  49. package/src/dto/resend-code-response.dto.ts +0 -32
  50. package/src/dto/resend-code.dto.ts +0 -51
  51. package/src/dto/reset-password.dto.ts +0 -115
  52. package/src/dto/respond-challenge.dto.ts +0 -272
  53. package/src/dto/set-mfa-exemption.dto.ts +0 -112
  54. package/src/dto/set-must-change-password-response.dto.ts +0 -27
  55. package/src/dto/set-must-change-password.dto.ts +0 -46
  56. package/src/dto/set-preferred-method.dto.ts +0 -80
  57. package/src/dto/setup-mfa.dto.ts +0 -98
  58. package/src/dto/signup.dto.ts +0 -174
  59. package/src/dto/social-auth.dto.ts +0 -422
  60. package/src/dto/trust-device-response.dto.ts +0 -30
  61. package/src/dto/trust-device.dto.ts +0 -9
  62. package/src/dto/update-user-attributes-request.dto.ts +0 -51
  63. package/src/dto/user-response.dto.ts +0 -138
  64. package/src/dto/user-update.dto.ts +0 -222
  65. package/src/dto/verify-email.dto.ts +0 -313
  66. package/src/dto/verify-mfa-code.dto.ts +0 -103
  67. package/src/dto/verify-phone-by-sub.dto.ts +0 -78
  68. package/src/dto/verify-phone.dto.ts +0 -245
  69. package/src/entities/auth-audit.entity.ts +0 -232
  70. package/src/entities/challenge-session.entity.ts +0 -116
  71. package/src/entities/index.ts +0 -29
  72. package/src/entities/login-attempt.entity.ts +0 -64
  73. package/src/entities/mfa-device.entity.ts +0 -151
  74. package/src/entities/rate-limit.entity.ts +0 -44
  75. package/src/entities/session.entity.ts +0 -180
  76. package/src/entities/social-account.entity.ts +0 -96
  77. package/src/entities/storage-lock.entity.ts +0 -39
  78. package/src/entities/trusted-device.entity.ts +0 -112
  79. package/src/entities/user.entity.ts +0 -243
  80. package/src/entities/verification-token.entity.ts +0 -141
  81. package/src/enums/auth-audit-event-type.enum.ts +0 -360
  82. package/src/enums/error-codes.enum.ts +0 -420
  83. package/src/enums/mfa-method.enum.ts +0 -97
  84. package/src/enums/risk-factor.enum.ts +0 -111
  85. package/src/exceptions/nauth.exception.ts +0 -231
  86. package/src/handlers/auth.handler.ts +0 -260
  87. package/src/handlers/client-info.handler.ts +0 -101
  88. package/src/handlers/csrf.handler.ts +0 -156
  89. package/src/handlers/token-delivery.handler.ts +0 -118
  90. package/src/index.ts +0 -118
  91. package/src/interfaces/client-info.interface.ts +0 -85
  92. package/src/interfaces/config.interface.ts +0 -2135
  93. package/src/interfaces/entities.interface.ts +0 -226
  94. package/src/interfaces/index.ts +0 -15
  95. package/src/interfaces/logger.interface.ts +0 -283
  96. package/src/interfaces/mfa-provider.interface.ts +0 -154
  97. package/src/interfaces/oauth.interface.ts +0 -148
  98. package/src/interfaces/provider.interface.ts +0 -47
  99. package/src/interfaces/social-auth-provider.interface.ts +0 -131
  100. package/src/interfaces/storage-adapter.interface.ts +0 -82
  101. package/src/interfaces/template.interface.ts +0 -510
  102. package/src/interfaces/token-verifier.interface.ts +0 -110
  103. package/src/internal.ts +0 -178
  104. package/src/platform/interfaces.ts +0 -299
  105. package/src/schemas/auth-config.schema.ts +0 -646
  106. package/src/services/adaptive-mfa-decision.service.spec.ts +0 -1058
  107. package/src/services/adaptive-mfa-decision.service.ts +0 -457
  108. package/src/services/auth-audit.service.spec.ts +0 -675
  109. package/src/services/auth-audit.service.ts +0 -558
  110. package/src/services/auth-challenge-helper.service.spec.ts +0 -3227
  111. package/src/services/auth-challenge-helper.service.ts +0 -825
  112. package/src/services/auth-flow-context-builder.service.ts +0 -520
  113. package/src/services/auth-flow-rules.ts +0 -202
  114. package/src/services/auth-flow-state-definitions.ts +0 -190
  115. package/src/services/auth-flow-state-machine.service.ts +0 -207
  116. package/src/services/auth-flow-state-machine.types.ts +0 -316
  117. package/src/services/auth.service.spec.ts +0 -4195
  118. package/src/services/auth.service.ts +0 -3727
  119. package/src/services/challenge.service.spec.ts +0 -1363
  120. package/src/services/challenge.service.ts +0 -696
  121. package/src/services/client-info.service.spec.ts +0 -572
  122. package/src/services/client-info.service.ts +0 -374
  123. package/src/services/csrf.service.ts +0 -54
  124. package/src/services/email-verification.service.spec.ts +0 -1229
  125. package/src/services/email-verification.service.ts +0 -578
  126. package/src/services/geo-location.service.spec.ts +0 -603
  127. package/src/services/geo-location.service.ts +0 -599
  128. package/src/services/index.ts +0 -13
  129. package/src/services/jwt.service.spec.ts +0 -882
  130. package/src/services/jwt.service.ts +0 -621
  131. package/src/services/mfa-base.service.spec.ts +0 -246
  132. package/src/services/mfa-base.service.ts +0 -611
  133. package/src/services/mfa.service.spec.ts +0 -693
  134. package/src/services/mfa.service.ts +0 -960
  135. package/src/services/password.service.spec.ts +0 -166
  136. package/src/services/password.service.ts +0 -309
  137. package/src/services/phone-verification.service.spec.ts +0 -1120
  138. package/src/services/phone-verification.service.ts +0 -751
  139. package/src/services/risk-detection.service.spec.ts +0 -1292
  140. package/src/services/risk-detection.service.ts +0 -1012
  141. package/src/services/risk-scoring.service.spec.ts +0 -204
  142. package/src/services/risk-scoring.service.ts +0 -131
  143. package/src/services/session.service.spec.ts +0 -1293
  144. package/src/services/session.service.ts +0 -803
  145. package/src/services/social-account.service.spec.ts +0 -725
  146. package/src/services/social-auth-base.service.spec.ts +0 -418
  147. package/src/services/social-auth-base.service.ts +0 -581
  148. package/src/services/social-auth.service.spec.ts +0 -238
  149. package/src/services/social-auth.service.ts +0 -436
  150. package/src/services/social-provider-registry.service.spec.ts +0 -238
  151. package/src/services/social-provider-registry.service.ts +0 -122
  152. package/src/services/trusted-device.service.spec.ts +0 -505
  153. package/src/services/trusted-device.service.ts +0 -339
  154. package/src/storage/account-lockout-storage.service.spec.ts +0 -310
  155. package/src/storage/account-lockout-storage.service.ts +0 -89
  156. package/src/storage/index.ts +0 -3
  157. package/src/storage/memory-storage.adapter.ts +0 -443
  158. package/src/storage/rate-limit-storage.service.spec.ts +0 -247
  159. package/src/storage/rate-limit-storage.service.ts +0 -38
  160. package/src/templates/html-template.engine.spec.ts +0 -161
  161. package/src/templates/html-template.engine.ts +0 -688
  162. package/src/templates/index.ts +0 -7
  163. package/src/utils/common-passwords.spec.ts +0 -230
  164. package/src/utils/common-passwords.ts +0 -170
  165. package/src/utils/context-storage.ts +0 -188
  166. package/src/utils/cookie-names.util.ts +0 -67
  167. package/src/utils/cookies.util.ts +0 -94
  168. package/src/utils/index.ts +0 -12
  169. package/src/utils/ip-extractor.spec.ts +0 -330
  170. package/src/utils/ip-extractor.ts +0 -220
  171. package/src/utils/nauth-logger.spec.ts +0 -388
  172. package/src/utils/nauth-logger.ts +0 -215
  173. package/src/utils/pii-redactor.spec.ts +0 -130
  174. package/src/utils/pii-redactor.ts +0 -288
  175. package/src/utils/setup/get-repositories.ts +0 -140
  176. package/src/utils/setup/init-services.ts +0 -422
  177. package/src/utils/setup/init-social.ts +0 -189
  178. package/src/utils/setup/init-storage.ts +0 -94
  179. package/src/utils/setup/register-mfa.ts +0 -165
  180. package/src/utils/setup/run-nauth-migrations.ts +0 -61
  181. package/src/utils/token-delivery-policy.ts +0 -38
  182. package/src/validators/template.validator.ts +0 -219
  183. package/tsconfig.json +0 -37
  184. package/tsconfig.lint.json +0 -6
@@ -1,2135 +0,0 @@
1
- /**
2
- * Configuration interface for nauth-toolkit
3
- *
4
- * NOTE: This interface is validated at runtime using Zod.
5
- * See packages/core/src/schemas/auth-config.schema.ts for validation rules.
6
- *
7
- * The Zod schema validates:
8
- * - Required fields and types
9
- * - Cross-dependencies (e.g., email config requires emailProvider)
10
- * - Algorithm-specific requirements (JWT symmetric vs asymmetric)
11
- * - MFA enforcement modes and their requirements
12
- * - Social provider requirements
13
- * - GeoLocation MaxMind credentials
14
- *
15
- * Validation errors are caught at module initialization with clear, actionable messages.
16
- */
17
-
18
- import { MFADeviceMethod } from '../enums/mfa-method.enum';
19
- import { StorageAdapter } from './storage-adapter.interface';
20
-
21
- export interface NAuthConfig {
22
- /**
23
- * Database table prefix
24
- *
25
- * @default 'nauth_'
26
- *
27
- * @example
28
- * ```typescript
29
- * tablePrefix: 'myapp_', // Tables: myapp_users, myapp_sessions, etc.
30
- * ```
31
- */
32
- tablePrefix?: string;
33
-
34
- /**
35
- * JWT configuration
36
- */
37
- jwt: JwtConfig;
38
-
39
- /**
40
- * Signup configuration
41
- */
42
- signup?: SignupConfig;
43
-
44
- /**
45
- * Login configuration
46
- */
47
- login?: LoginConfig;
48
-
49
- /**
50
- * Password policy configuration
51
- */
52
- password?: PasswordConfig;
53
-
54
- /**
55
- * Account lockout configuration
56
- */
57
- lockout?: LockoutConfig;
58
-
59
- /**
60
- * Session configuration
61
- */
62
- session?: SessionConfig;
63
-
64
- /**
65
- * Security configuration
66
- */
67
- security?: SecurityConfig;
68
-
69
- /**
70
- * Lifecycle hooks
71
- */
72
- hooks?: LifecycleHooks;
73
-
74
- /**
75
- * Audit logging configuration
76
- *
77
- * Controls whether authentication and security events are logged to the audit trail.
78
- * When disabled, audit logs are not recorded, reducing storage costs and minor performance overhead.
79
- *
80
- * WARNING: Highly recommended for production systems. Disabling audit logs reduces security observability.
81
- *
82
- * @default { enabled: true }
83
- *
84
- * @example
85
- * ```typescript
86
- * // Enable audit logs (default - recommended for production)
87
- * auditLogs: {
88
- * enabled: true
89
- * }
90
- *
91
- * // Disable audit logs (minimal overhead use cases only)
92
- * auditLogs: {
93
- * enabled: false
94
- * }
95
- * ```
96
- */
97
- auditLogs?: {
98
- /**
99
- * Enable audit logging
100
- * @default true
101
- */
102
- enabled?: boolean;
103
- /**
104
- * Fire-and-forget audit mode for hot paths
105
- * When true, audit writes won't be awaited on request path
106
- */
107
- fireAndForget?: boolean;
108
- };
109
-
110
- /**
111
- * Email provider for sending verification emails, password resets, etc.
112
- *
113
- * Configure based on your needs - consumer apps choose their own env var names.
114
- * All values should be passed explicitly through config, not auto-loaded.
115
- *
116
- * @example
117
- * ```typescript
118
- * // Console provider (development - logs to console)
119
- * import { ConsoleEmailProvider } from '@nauth-toolkit/email-console';
120
- * emailProvider: new ConsoleEmailProvider()
121
- *
122
- * // Nodemailer with SMTP (production)
123
- * import { NodemailerEmailProvider } from '@nauth-toolkit/email-nodemailer';
124
- * emailProvider: new NodemailerEmailProvider({
125
- * transport: {
126
- * host: process.env.SMTP_HOST, // Your env var name
127
- * port: parseInt(process.env.SMTP_PORT || '587'),
128
- * secure: process.env.SMTP_SECURE === 'true',
129
- * auth: {
130
- * user: process.env.SMTP_USER,
131
- * pass: process.env.SMTP_PASS,
132
- * },
133
- * },
134
- * defaults: {
135
- * from: process.env.EMAIL_FROM, // e.g., "My App <noreply@example.com>"
136
- * },
137
- * })
138
- * ```
139
- */
140
- emailProvider?: any; // EmailProvider type will be imported from provider.interface
141
-
142
- /**
143
- * Email verification configuration
144
- */
145
- email?: EmailConfig;
146
-
147
- /**
148
- * Optional: SMS provider for sending phone verification codes
149
- * If not provided, uses ConsoleSMSProvider (logs to console)
150
- *
151
- * @example
152
- * ```typescript
153
- * // Use console provider (development)
154
- * smsProvider: new ConsoleSMSProvider()
155
- *
156
- * // Use Twilio provider (production)
157
- * smsProvider: new TwilioSMSProvider({ accountSid: '...', authToken: '...', fromNumber: '...' })
158
- * ```
159
- */
160
- smsProvider?: any; // SMSProvider type will be imported from provider.interface
161
-
162
- /**
163
- * Phone verification configuration
164
- */
165
- phone?: PhoneConfig;
166
-
167
- /**
168
- * Storage adapter for transient state (rate limits, locks, token reuse tracking)
169
- *
170
- * WARNING: PRODUCTION REQUIREMENT - Storage adapter is REQUIRED for production deployments.
171
- *
172
- * Default Behavior:
173
- * - If not provided and storage entities are available: DatabaseStorageAdapter is used automatically
174
- * - If not provided and storage entities are NOT available: Configuration fails with helpful error message
175
- *
176
- * MemoryStorageAdapter is NOT safe for production:
177
- * - Data lost on server restart
178
- * - NOT shared across multiple server instances
179
- * - Rate limiting per-container (not global in multi-container setups)
180
- * - Token reuse detection fails in multi-server deployments
181
- *
182
- * Recommended: DatabaseStorageAdapter (default, uses existing TypeORM connection, no additional infrastructure)
183
- * Alternative: RedisStorageAdapter (for high-performance multi-server deployments)
184
- * Production: RedisClusterAdapter (for high-availability production clusters)
185
- *
186
- * @example
187
- * ```typescript
188
- * // Database adapter (default - uses existing TypeORM connection, no additional infrastructure)
189
- * import { createDatabaseStorageAdapter } from '@nauth-toolkit/nestjs';
190
- * storageAdapter: createDatabaseStorageAdapter()
191
- *
192
- * // Redis adapter (for high-performance multi-server deployments)
193
- * import { createRedisStorageAdapter } from '@nauth-toolkit/nestjs';
194
- * storageAdapter: createRedisStorageAdapter(process.env.REDIS_URL)
195
- *
196
- * // Redis Cluster adapter (for high-availability production deployments)
197
- * import { createRedisClusterAdapter } from '@nauth-toolkit/nestjs';
198
- * storageAdapter: createRedisClusterAdapter([
199
- * { url: 'redis://redis-node-1:6379' },
200
- * { url: 'redis://redis-node-2:6379' },
201
- * { url: 'redis://redis-node-3:6379' },
202
- * ])
203
- *
204
- * // Auto-detect (uses DatabaseStorageAdapter if entities available)
205
- * storageAdapter: undefined
206
- * ```
207
- */
208
- storageAdapter?: StorageAdapter;
209
-
210
- /**
211
- * Social login configuration
212
- * Configure OAuth providers for social authentication
213
- *
214
- * @example
215
- * ```typescript
216
- * social: {
217
- * google: {
218
- * enabled: true,
219
- * clientId: process.env.GOOGLE_CLIENT_ID, // Your env var name
220
- * clientSecret: process.env.GOOGLE_CLIENT_SECRET,
221
- * callbackUrl: 'https://myapp.com/auth/google/callback',
222
- * autoLink: true,
223
- * allowSignup: true
224
- * },
225
- * apple: {
226
- * enabled: true,
227
- * clientId: process.env.APPLE_CLIENT_ID, // Your env var name
228
- * clientSecret: process.env.APPLE_CLIENT_SECRET,
229
- * callbackUrl: 'https://myapp.com/auth/apple/callback',
230
- * autoLink: true,
231
- * allowSignup: true
232
- * }
233
- * }
234
- * ```
235
- */
236
- social?: SocialConfig;
237
-
238
- /**
239
- * Multi-Factor Authentication (MFA) configuration
240
- *
241
- * Supports multiple MFA methods: TOTP (authenticator apps), SMS, Email, and Passkeys (WebAuthn).
242
- * Users can register multiple devices for redundancy.
243
- *
244
- * @example
245
- * ```typescript
246
- * mfa: {
247
- * enabled: true,
248
- * enforcement: 'OPTIONAL',
249
- * allowedMethods: [MFAMethod.TOTP, MFAMethod.SMS, MFAMethod.EMAIL, MFAMethod.PASSKEY],
250
- * issuer: 'MyApp',
251
- * totp: {
252
- * window: 1,
253
- * stepSeconds: 30
254
- * },
255
- * passkey: {
256
- * rpName: 'MyApp',
257
- * rpId: 'myapp.com',
258
- * timeout: 60000
259
- * },
260
- * backup: {
261
- * enabled: true,
262
- * codeCount: 10
263
- * }
264
- * }
265
- * ```
266
- */
267
- mfa?: MFAConfig;
268
-
269
- /**
270
- * Optional: Logger configuration for nauth-toolkit internal logging
271
- * Compatible with NestJS LoggerService interface
272
- * If not provided, nauth-toolkit will be silent (no logs)
273
- *
274
- * All logs will be prefixed with "NAUTH:" for easy identification
275
- * PII redaction is enabled by default for security compliance
276
- *
277
- * @example
278
- * ```typescript
279
- * import { Logger } from '@nestjs/common';
280
- *
281
- * // Use NestJS built-in logger with default settings (PII redaction enabled)
282
- * logger: new Logger('NAuth')
283
- *
284
- * // Use custom logger with options
285
- * logger: {
286
- * instance: new Logger('NAuth'),
287
- * enablePiiRedaction: true, // Default: true
288
- * logLevel: 'debug' // Optional: control log level
289
- * }
290
- *
291
- * // Disable PII redaction (for debugging - not recommended in production)
292
- * logger: {
293
- * instance: myCustomLogger,
294
- * enablePiiRedaction: false
295
- * }
296
- *
297
- * // No logger = silent mode (default)
298
- * logger: undefined
299
- * ```
300
- */
301
- logger?: LoggerService | NAuthLoggerConfig;
302
-
303
- /**
304
- * Token delivery configuration
305
- *
306
- * Controls how JWT tokens are delivered to clients.
307
- * - 'json': Return tokens in response body only (default, protocol-agnostic)
308
- * - 'cookies': Set tokens as httpOnly cookies only (browser web apps)
309
- * - 'hybrid': Strict hybrid: cookies for web origins, JSON for native; never both
310
- *
311
- * Smart defaults (non-configurable unless explicitly overridden):
312
- * - Cookie names: 'nauth_access_token', 'nauth_refresh_token'
313
- * - httpOnly: true (always)
314
- * - secure: true (configurable for localhost/dev)
315
- * - sameSite: 'strict' (configurable)
316
- * - path: '/' (configurable)
317
- *
318
- * @default { method: 'json' }
319
- *
320
- * @example
321
- * // Minimal (99% of use cases)
322
- * tokenDelivery: { method: 'cookies' }
323
- *
324
- * // With overrides (rare)
325
- * tokenDelivery: {
326
- * method: 'hybrid',
327
- * cookieOptions: {
328
- * secure: false, // For localhost development
329
- * domain: '.myapp.com', // For subdomain sharing
330
- * }
331
- * }
332
- */
333
- tokenDelivery?: TokenDeliveryConfig;
334
-
335
- /**
336
- * Challenge configuration
337
- *
338
- * Controls challenge session behavior for authentication challenges
339
- * (email verification, phone verification, MFA challenges, etc.)
340
- *
341
- * @example
342
- * ```typescript
343
- * challenge: {
344
- * maxAttempts: 3 // Default: 3 attempts (4th failure causes error)
345
- * }
346
- * ```
347
- */
348
- challenge?: ChallengeConfig;
349
-
350
- /**
351
- * Geolocation configuration
352
- *
353
- * Configures IP geolocation using MaxMind GeoIP2 database files.
354
- * Platform-agnostic - works on all platforms where Node.js runs.
355
- *
356
- * @example
357
- * ```typescript
358
- * geoLocation: {
359
- * maxMind: {
360
- * licenseKey: process.env.MAXMIND_LICENSE_KEY,
361
- * accountId: parseInt(process.env.MAXMIND_ACCOUNT_ID || '0'),
362
- * // dbPath not set = uses system temp directory
363
- * }
364
- * }
365
- * ```
366
- */
367
- geoLocation?: GeoLocationConfig;
368
- }
369
-
370
- /**
371
- * NAuth logger configuration with PII redaction options
372
- */
373
- export interface NAuthLoggerConfig {
374
- /**
375
- * Logger instance (NestJS Logger, Winston, Pino, or custom)
376
- */
377
- instance: LoggerService;
378
-
379
- /**
380
- * Enable PII redaction (default: true)
381
- * Automatically redacts emails, IPs, tokens, phone numbers, etc.
382
- *
383
- * WARNING: Only disable for debugging in development
384
- */
385
- enablePiiRedaction?: boolean;
386
-
387
- /**
388
- * Optional: Control minimum log level
389
- * If not set, all log methods will be called (logger decides what to output)
390
- */
391
- logLevel?: 'error' | 'warn' | 'log' | 'debug' | 'verbose';
392
- }
393
-
394
- /**
395
- * Logger interface compatible with NestJS LoggerService
396
- * Supports any logger that implements these methods
397
- */
398
- export interface LoggerService {
399
- log(message: any, ...optionalParams: any[]): any;
400
- error(message: any, ...optionalParams: any[]): any;
401
- warn(message: any, ...optionalParams: any[]): any;
402
- debug?(message: any, ...optionalParams: any[]): any;
403
- verbose?(message: any, ...optionalParams: any[]): any;
404
- }
405
-
406
- export interface JwtConfig {
407
- /**
408
- * JWT algorithm
409
- *
410
- * - HS256/HS384/HS512: HMAC with SHA (symmetric key, default: HS256)
411
- * - RS256/RS384/RS512: RSA with SHA (asymmetric key pair)
412
- */
413
- algorithm?: 'HS256' | 'HS384' | 'HS512' | 'RS256' | 'RS384' | 'RS512';
414
-
415
- /**
416
- * Access token configuration
417
- */
418
- accessToken: AccessTokenConfig;
419
-
420
- /**
421
- * Refresh token configuration
422
- */
423
- refreshToken: RefreshTokenConfig;
424
-
425
- /**
426
- * Token issuer
427
- */
428
- issuer?: string;
429
-
430
- /**
431
- * Token audience
432
- */
433
- audience?: string | string[];
434
- }
435
-
436
- export interface AccessTokenConfig {
437
- /**
438
- * Secret key for symmetric algorithms (HS256/HS384/HS512)
439
- * Base64-encoded string
440
- */
441
- secret?: string;
442
-
443
- /**
444
- * Private key for asymmetric algorithms (RS256/RS384/RS512)
445
- * PEM-encoded private key
446
- */
447
- privateKey?: string;
448
-
449
- /**
450
- * Public key for asymmetric algorithms (RS256/RS384/RS512)
451
- * PEM-encoded public key
452
- */
453
- publicKey?: string;
454
-
455
- /**
456
- * Token expiration time (e.g., '15m', '1h', 900)
457
- */
458
- expiresIn: string | number;
459
- }
460
-
461
- export interface RefreshTokenConfig {
462
- /**
463
- * Secret key for signing (typically uses HS256 for refresh tokens)
464
- * Base64-encoded string
465
- */
466
- secret: string;
467
-
468
- /**
469
- * Token expiration time (e.g., '30d', '7d')
470
- */
471
- expiresIn: string | number;
472
-
473
- /**
474
- * Enable token rotation (generate new refresh token on each use)
475
- */
476
- rotation?: boolean;
477
-
478
- /**
479
- * Enable refresh token reuse detection
480
- */
481
- reuseDetection?: boolean;
482
- }
483
-
484
- export interface SignupConfig {
485
- /**
486
- * Enable user signups
487
- * If false, signup endpoint will return 403 Forbidden
488
- *
489
- * Default: true
490
- */
491
- enabled?: boolean;
492
-
493
- /**
494
- * Verification method requirement
495
- *
496
- * Options:
497
- * - 'none': No verification required (users can login immediately)
498
- * - 'email': Email verification required before login (default)
499
- * - 'phone': Phone verification required before login
500
- * - 'both': BOTH email AND phone verification required
501
- *
502
- * Default: 'email'
503
- *
504
- * @example
505
- * ```typescript
506
- * // No verification (auto-activate)
507
- * signup: { verificationMethod: 'none' }
508
- *
509
- * // Email only (default)
510
- * signup: { verificationMethod: 'email' }
511
- *
512
- * // Both required
513
- * signup: { verificationMethod: 'both' }
514
- * ```
515
- */
516
- verificationMethod?: 'none' | 'email' | 'phone' | 'both';
517
-
518
- /**
519
- * Allow duplicate phone numbers
520
- * If true, multiple users can have the same phone number
521
- * Phone verification will be user-specific (requires user sub)
522
- *
523
- * Default: false
524
- *
525
- * @example
526
- * ```typescript
527
- * // Allow shared phone numbers (family accounts, etc.)
528
- * signup: { allowDuplicatePhones: true }
529
- * ```
530
- */
531
- allowDuplicatePhones?: boolean;
532
-
533
- /**
534
- * Email verification settings
535
- * Only relevant when verificationMethod is 'email' or 'both'
536
- */
537
- emailVerification?: {
538
- /**
539
- * Code expiry in seconds
540
- * @default 3600 (1 hour)
541
- */
542
- expiresIn?: number;
543
-
544
- /**
545
- * Delay between resend requests in seconds
546
- * Prevents users from requesting codes too frequently
547
- * @default 60
548
- */
549
- resendDelay?: number;
550
-
551
- /**
552
- * Maximum email verification codes per time window
553
- * Prevents email abuse and rate limiting
554
- * @default 3
555
- */
556
- rateLimitMax?: number;
557
-
558
- /**
559
- * Rate limit time window in seconds
560
- * The time period over which rateLimitMax applies
561
- * @default 3600 (1 hour)
562
- *
563
- * @example
564
- * ```typescript
565
- * // Allow 5 emails per hour
566
- * rateLimitMax: 5,
567
- * rateLimitWindow: 3600, // 1 hour
568
- *
569
- * // Allow 3 emails per 15 minutes (stricter)
570
- * rateLimitMax: 3,
571
- * rateLimitWindow: 900, // 15 minutes
572
- * ```
573
- */
574
- rateLimitWindow?: number;
575
-
576
- /**
577
- * Maximum verification attempts per user per time window
578
- * Limits how many times a user can attempt to verify their email with a code
579
- * @default 10
580
- */
581
- maxAttemptsPerUser?: number;
582
-
583
- /**
584
- * Maximum verification attempts per IP per time window
585
- * Limits how many verification attempts can be made from a single IP address
586
- * @default 20
587
- */
588
- maxAttemptsPerIP?: number;
589
-
590
- /**
591
- * Verification attempt rate limit window in seconds
592
- * The time period over which maxAttemptsPerUser and maxAttemptsPerIP apply
593
- * @default 3600 (1 hour)
594
- */
595
- attemptWindow?: number;
596
- };
597
-
598
- /**
599
- * Phone verification settings
600
- * Only relevant when verificationMethod is 'phone' or 'both'
601
- */
602
- phoneVerification?: {
603
- /**
604
- * OTP code length
605
- * @default 6
606
- */
607
- codeLength?: number;
608
-
609
- /**
610
- * Code expiry in seconds
611
- * @default 300 (5 minutes)
612
- */
613
- expiresIn?: number;
614
-
615
- /**
616
- * Maximum verification attempts per code
617
- * @default 3
618
- */
619
- maxAttempts?: number;
620
-
621
- /**
622
- * Delay between resend requests in seconds
623
- * Prevents users from requesting codes too frequently
624
- * @default 60
625
- */
626
- resendDelay?: number;
627
-
628
- /**
629
- * Maximum SMS verification codes per time window
630
- * Prevents SMS abuse and rate limiting
631
- * @default 3
632
- */
633
- rateLimitMax?: number;
634
-
635
- /**
636
- * Rate limit time window in seconds
637
- * The time period over which rateLimitMax applies
638
- * @default 3600 (1 hour)
639
- *
640
- * @example
641
- * ```typescript
642
- * // Allow 5 SMS codes per hour
643
- * rateLimitMax: 5,
644
- * rateLimitWindow: 3600, // 1 hour
645
- *
646
- * // Allow 3 SMS codes per 15 minutes (stricter)
647
- * rateLimitMax: 3,
648
- * rateLimitWindow: 900, // 15 minutes
649
- * ```
650
- */
651
- rateLimitWindow?: number;
652
-
653
- /**
654
- * Maximum verification attempts per user per time window
655
- * Limits how many times a user can attempt to verify their phone with a code
656
- * @default 10
657
- */
658
- maxAttemptsPerUser?: number;
659
-
660
- /**
661
- * Maximum verification attempts per IP per time window
662
- * Limits how many verification attempts can be made from a single IP address
663
- * @default 20
664
- */
665
- maxAttemptsPerIP?: number;
666
-
667
- /**
668
- * Verification attempt rate limit window in seconds
669
- * The time period over which maxAttemptsPerUser and maxAttemptsPerIP apply
670
- * @default 3600 (1 hour)
671
- */
672
- attemptWindow?: number;
673
- };
674
- }
675
-
676
- export interface LoginConfig {
677
- /**
678
- * Identifier type for login
679
- *
680
- * Controls which identifier types are accepted during login:
681
- * - 'email': Only email addresses accepted
682
- * - 'username': Only usernames accepted
683
- * - 'phone': Only phone numbers accepted
684
- * - 'email_or_username': Both email and username accepted (phone excluded)
685
- *
686
- * @default undefined (all types accepted: email, username, phone)
687
- *
688
- * @example
689
- * ```typescript
690
- * // Only allow email login
691
- * login: {
692
- * identifierType: 'email'
693
- * }
694
- *
695
- * // Allow email or username (not phone)
696
- * login: {
697
- * identifierType: 'email_or_username'
698
- * }
699
- * ```
700
- */
701
- identifierType?: 'email' | 'username' | 'phone' | 'email_or_username';
702
- }
703
-
704
- export interface PasswordConfig {
705
- /**
706
- * Minimum password length
707
- */
708
- minLength?: number;
709
-
710
- /**
711
- * Maximum password length
712
- */
713
- maxLength?: number;
714
-
715
- /**
716
- * Require uppercase letters
717
- */
718
- requireUppercase?: boolean;
719
-
720
- /**
721
- * Require lowercase letters
722
- */
723
- requireLowercase?: boolean;
724
-
725
- /**
726
- * Require numbers
727
- */
728
- requireNumbers?: boolean;
729
-
730
- /**
731
- * Require special characters
732
- */
733
- requireSpecialChars?: boolean;
734
-
735
- /**
736
- * Allowed special characters
737
- */
738
- specialChars?: string;
739
-
740
- /**
741
- * Prevent common passwords
742
- */
743
- preventCommon?: boolean;
744
-
745
- /**
746
- * Prevent username/email in password
747
- */
748
- preventUserInfo?: boolean;
749
-
750
- /**
751
- * Password history count (prevent reuse)
752
- */
753
- historyCount?: number;
754
-
755
- /**
756
- * Password expiry in days (0 = disabled)
757
- */
758
- expiryDays?: number;
759
- }
760
-
761
- export interface LockoutConfig {
762
- /**
763
- * Enable IP-based account lockout
764
- *
765
- * SECURITY: Uses IP addresses instead of user identifiers to prevent
766
- * attackers from locking out legitimate users by guessing their email/username.
767
- */
768
- enabled?: boolean;
769
-
770
- /**
771
- * Maximum failed login attempts per IP address
772
- */
773
- maxAttempts?: number;
774
-
775
- /**
776
- * IP lockout duration in seconds
777
- */
778
- duration?: number;
779
-
780
- /**
781
- * Reset IP counter on successful login
782
- */
783
- resetOnSuccess?: boolean;
784
- }
785
-
786
- export interface SessionConfig {
787
- /**
788
- * Maximum concurrent sessions per user
789
- */
790
- maxConcurrent?: number;
791
-
792
- /**
793
- * Disallow multiple concurrent sessions
794
- * When enabled, only one active session is allowed per user.
795
- * When a user logs in on a new device/session, all other sessions are automatically logged out.
796
- *
797
- * @default false
798
- *
799
- * @example
800
- * ```typescript
801
- * // Only allow one active session per user
802
- * session: {
803
- * disallowMultipleSessions: true
804
- * }
805
- *
806
- * // Allow multiple sessions (default)
807
- * session: {
808
- * disallowMultipleSessions: false
809
- * }
810
- * ```
811
- */
812
- disallowMultipleSessions?: boolean;
813
-
814
- /**
815
- * Maximum session lifetime (hard limit)
816
- *
817
- * This is the maximum duration a session can exist, regardless of refresh token activity.
818
- * Even if a user actively refreshes their tokens daily, after this time they must re-authenticate.
819
- *
820
- * This provides a security boundary to force periodic re-authentication, preventing
821
- * indefinite sessions even for very active users.
822
- *
823
- * Format: String (e.g., '30d', '7d', '90d', '5h') or number (seconds)
824
- * - 's' = seconds
825
- * - 'm' = minutes
826
- * - 'h' = hours
827
- * - 'd' = days
828
- *
829
- * @default '30d' (30 days)
830
- *
831
- * @example
832
- * ```typescript
833
- * // 30 days (default)
834
- * session: {
835
- * maxLifetime: '30d'
836
- * }
837
- *
838
- * // 90 days (more lenient)
839
- * session: {
840
- * maxLifetime: '90d'
841
- * }
842
- *
843
- * // 7 days (stricter)
844
- * session: {
845
- * maxLifetime: '7d'
846
- * }
847
- *
848
- * // Using seconds
849
- * session: {
850
- * maxLifetime: 2592000 // 30 days in seconds
851
- * }
852
- * ```
853
- */
854
- maxLifetime?: string | number;
855
- }
856
-
857
- export interface SecurityConfig {
858
- /**
859
- * CSRF Protection Configuration
860
- *
861
- * WARNING: SECURITY - CSRF protection is REQUIRED when using cookie-based token delivery
862
- * (tokenDelivery.method === 'cookies' or 'hybrid' with web origins).
863
- *
864
- * CSRF protection prevents Cross-Site Request Forgery attacks when tokens are stored in cookies.
865
- * The CSRF Guard is automatically registered when tokenDelivery.method === 'cookies' or 'hybrid'.
866
- * CSRF tokens are automatically generated and set as cookies on login/refresh.
867
- *
868
- * Frontend must:
869
- * 1. Read CSRF token from cookie (cookieName)
870
- * 2. Send CSRF token in request header (headerName) for state-changing requests (POST, PUT, DELETE, PATCH)
871
- * 3. Skip for safe methods (GET, HEAD, OPTIONS) - these don't require CSRF token
872
- *
873
- * CSRF protection is NOT required for JSON token delivery (Bearer tokens in headers are CSRF-safe).
874
- *
875
- * @example
876
- * ```typescript
877
- * // CSRF configuration (required for cookie-based token delivery)
878
- * security: {
879
- * csrf: {
880
- * cookieName: 'csrf-token',
881
- * headerName: 'x-csrf-token',
882
- * tokenLength: 32,
883
- * excludedPaths: ['/webhook'] // Exclude webhook endpoints
884
- * }
885
- * }
886
- * ```
887
- */
888
- csrf?: {
889
- /**
890
- * Name of the CSRF cookie
891
- *
892
- * If not provided, defaults to `${tokenDelivery.cookieNamePrefix || 'nauth_'}csrf_token`
893
- * (e.g., 'nauth_csrf_token' with default prefix).
894
- *
895
- * The prefix ensures consistency with other auth cookie names and avoids conflicts.
896
- *
897
- * @default `${tokenDelivery.cookieNamePrefix || 'nauth_'}csrf_token`
898
- */
899
- cookieName?: string;
900
-
901
- /**
902
- * Name of the CSRF header to check
903
- * Default: 'x-csrf-token'
904
- */
905
- headerName?: string;
906
-
907
- /**
908
- * Length of CSRF token in bytes
909
- * Default: 32 (256 bits)
910
- */
911
- tokenLength?: number;
912
-
913
- /**
914
- * Excluded paths (no CSRF check)
915
- * Useful for webhook endpoints or public APIs
916
- * Default: []
917
- *
918
- * @example
919
- * excludedPaths: ['/webhook', '/public-api']
920
- */
921
- excludedPaths?: string[];
922
-
923
- /**
924
- * Cookie options for CSRF token
925
- * Default: { secure: true, sameSite: 'strict' }
926
- *
927
- * Note: httpOnly is always false (hardcoded) - CSRF token must be readable by JavaScript
928
- */
929
- cookieOptions?: {
930
- /**
931
- * Secure cookies (HTTPS only)
932
- * Set to false for localhost development
933
- * @default true
934
- */
935
- secure?: boolean;
936
- /**
937
- * SameSite cookie attribute
938
- * - 'strict': Most secure, cookies only sent on same-site requests
939
- * - 'lax': Cookies sent on same-site + top-level navigation (e.g., link from Google)
940
- * - 'none': Cookies sent on all requests (requires secure: true)
941
- * @default 'strict'
942
- */
943
- sameSite?: 'strict' | 'lax' | 'none';
944
- /**
945
- * Cookie domain (for subdomain sharing)
946
- * @example '.dev1.noorix.com' to share across subdomains
947
- */
948
- domain?: string;
949
- /**
950
- * Cookie path
951
- * @default '/'
952
- */
953
- path?: string;
954
- };
955
- };
956
- }
957
-
958
- export interface LifecycleHooks {
959
- /**
960
- * After signup hook
961
- */
962
- afterSignup?: (user: any, metadata?: { requiresVerification?: boolean }) => Promise<void>;
963
-
964
- afterLogin?: (user: any, session: any) => Promise<void>;
965
-
966
- /**
967
- * After login failed hook
968
- */
969
- afterLoginFailed?: (identifier: string, reason: string) => Promise<void>;
970
-
971
- /**
972
- * Before password change hook
973
- */
974
- beforePasswordChange?: (userId: string, oldPassword: string) => Promise<void | false>;
975
-
976
- /**
977
- * After password change hook
978
- */
979
- afterPasswordChange?: (userId: string) => Promise<void>;
980
-
981
- /**
982
- * Before account lock hook
983
- */
984
- beforeAccountLock?: (userId: string, reason: string) => Promise<void | false>;
985
-
986
- /**
987
- * After account lock hook
988
- */
989
- afterAccountLock?: (userId: string, reason: string) => Promise<void>;
990
-
991
- /**
992
- * Adaptive MFA risk detected hook
993
- *
994
- * Called when adaptive MFA evaluates a login attempt and detects risk.
995
- * Allows consumer app to send custom notifications, log to external systems,
996
- * trigger security workflows, etc.
997
- *
998
- * This hook is called BEFORE the action is enforced (allow/require_mfa/block).
999
- * Return false to override the adaptive decision and allow sign-in.
1000
- *
1001
- * @param payload - Rich context about the risk event
1002
- * @returns void to continue with configured action, false to override and allow
1003
- *
1004
- * @example Email notification
1005
- * ```typescript
1006
- * onAdaptiveMFATriggered: async (payload) => {
1007
- * if (payload.riskLevel === 'high') {
1008
- * await emailService.send({
1009
- * to: payload.user.email,
1010
- * subject: 'Suspicious sign-in attempt detected',
1011
- * template: 'security-alert',
1012
- * data: {
1013
- * location: `${payload.clientInfo.ipCity}, ${payload.clientInfo.ipCountry}`,
1014
- * device: payload.clientInfo.deviceName,
1015
- * time: new Date().toISOString(),
1016
- * riskFactors: payload.riskFactors.join(', '),
1017
- * }
1018
- * });
1019
- * }
1020
- * }
1021
- * ```
1022
- *
1023
- * @example Slack notification to security team
1024
- * ```typescript
1025
- * onAdaptiveMFATriggered: async (payload) => {
1026
- * if (payload.action === 'block_signin') {
1027
- * await slackService.postMessage({
1028
- * channel: '#security-alerts',
1029
- * text: `High-risk sign-in blocked for ${payload.user.email}`,
1030
- * attachments: [{
1031
- * fields: [
1032
- * { title: 'Risk Score', value: payload.riskScore.toString() },
1033
- * { title: 'Risk Factors', value: payload.riskFactors.join(', ') },
1034
- * { title: 'Location', value: payload.clientInfo.ipCountry },
1035
- * ]
1036
- * }]
1037
- * });
1038
- * }
1039
- * }
1040
- * ```
1041
- *
1042
- * @example Custom workflow with admin review
1043
- * ```typescript
1044
- * onAdaptiveMFATriggered: async (payload) => {
1045
- * if (payload.riskScore > 80) {
1046
- * // Create security review ticket
1047
- * await securityReviewService.createTicket({
1048
- * userId: payload.user.sub,
1049
- * riskScore: payload.riskScore,
1050
- * riskFactors: payload.riskFactors,
1051
- * requiresManualReview: true,
1052
- * });
1053
- *
1054
- * // Send push notification to admins
1055
- * await adminNotificationService.alert({
1056
- * type: 'high_risk_signin',
1057
- * userId: payload.user.sub,
1058
- * });
1059
- * }
1060
- * }
1061
- * ```
1062
- */
1063
- onAdaptiveMFATriggered?: (payload: AdaptiveMFARiskEventPayload) => Promise<void | false>;
1064
-
1065
- /**
1066
- * Sign-in blocked hook
1067
- *
1068
- * Called when a sign-in is blocked due to high risk.
1069
- * Allows consumer app to implement custom blocking workflows,
1070
- * manual review processes, or admin notifications.
1071
- *
1072
- * @param payload - Context about the blocked sign-in
1073
- *
1074
- * @example Create manual review case
1075
- * ```typescript
1076
- * onSignInBlocked: async (payload) => {
1077
- * await adminDashboardService.createReviewCase({
1078
- * userId: payload.user.sub,
1079
- * reason: 'High-risk adaptive MFA',
1080
- * riskScore: payload.riskScore,
1081
- * requiresAction: true,
1082
- * });
1083
- * }
1084
- * ```
1085
- */
1086
- onSignInBlocked?: (payload: SignInBlockedPayload) => Promise<void>;
1087
- }
1088
-
1089
- /**
1090
- * Email Verification Configuration
1091
- */
1092
- export interface EmailConfig {
1093
- /**
1094
- * Application name (used in email templates)
1095
- *
1096
- * @example 'My Application'
1097
- */
1098
- appName?: string;
1099
-
1100
- /**
1101
- * Company name (used in email footer)
1102
- *
1103
- * @example 'My Company Inc.'
1104
- */
1105
- companyName?: string;
1106
-
1107
- /**
1108
- * Logo URL for email templates
1109
- *
1110
- * @example 'https://example.com/logo.png'
1111
- */
1112
- logoUrl?: string;
1113
-
1114
- /**
1115
- * Support email address (displayed in email footer)
1116
- *
1117
- * @example 'support@example.com'
1118
- */
1119
- supportEmail?: string;
1120
-
1121
- /**
1122
- * Dashboard URL (used in welcome emails)
1123
- *
1124
- * @example 'https://app.example.com/dashboard'
1125
- */
1126
- dashboardUrl?: string;
1127
-
1128
- /**
1129
- * Brand color (hex code, used in email templates)
1130
- *
1131
- * @example '#4f46e5'
1132
- */
1133
- brandColor?: string;
1134
-
1135
- /**
1136
- * Custom footer disclaimer text
1137
- *
1138
- * If not provided, uses default professional disclaimer.
1139
- *
1140
- * @example 'This email is confidential. Unsubscribe at any time.'
1141
- */
1142
- footerDisclaimer?: string;
1143
-
1144
- /**
1145
- * Template configuration for email notifications
1146
- *
1147
- * Configure custom email templates and global variables for branding.
1148
- * Templates are validated at startup to ensure required parameters are present.
1149
- *
1150
- * Note: Top-level branding fields (appName, companyName, logoUrl, etc.) are automatically
1151
- * merged into templates.globalVariables. You can override them in globalVariables if needed.
1152
- *
1153
- * @example Basic configuration with top-level branding
1154
- * ```typescript
1155
- * email: {
1156
- * appName: process.env.APP_NAME || 'My Application',
1157
- * companyName: process.env.COMPANY_NAME || 'My Company Inc.',
1158
- * supportEmail: process.env.SUPPORT_EMAIL || 'support@example.com',
1159
- * brandColor: '#4f46e5',
1160
- * logoUrl: 'https://example.com/logo.png'
1161
- * }
1162
- * ```
1163
- *
1164
- * @example Advanced configuration with global variables
1165
- * ```typescript
1166
- * email: {
1167
- * appName: 'My App',
1168
- * companyName: 'My Company',
1169
- * templates: {
1170
- * globalVariables: {
1171
- * // These override top-level values if both are provided
1172
- * appName: 'Custom App Name',
1173
- * customVar: 'Custom value'
1174
- * }
1175
- * }
1176
- * }
1177
- * ```
1178
- *
1179
- * @example Custom templates with file paths
1180
- * ```typescript
1181
- * email: {
1182
- * templates: {
1183
- * globalVariables: {
1184
- * appName: 'My App',
1185
- * supportEmail: 'support@myapp.com'
1186
- * },
1187
- * customTemplates: {
1188
- * verification: {
1189
- * htmlPath: './email-templates/verification.html.hbs',
1190
- * textPath: './email-templates/verification.text.hbs'
1191
- * // Must include: {{code}}, {{link}}, {{expiryMinutes}}
1192
- * },
1193
- * welcome: {
1194
- * htmlPath: './email-templates/welcome.html.hbs'
1195
- * // No required params
1196
- * }
1197
- * }
1198
- * }
1199
- * }
1200
- * ```
1201
- *
1202
- * @example Custom templates with inline content
1203
- * ```typescript
1204
- * email: {
1205
- * templates: {
1206
- * globalVariables: { appName: 'My App' },
1207
- * customTemplates: {
1208
- * welcome: {
1209
- * subject: 'Welcome to {{appName}}!',
1210
- * html: `
1211
- * <h1>Hello {{firstName}}!</h1>
1212
- * <p>Welcome to {{appName}}!</p>
1213
- * `,
1214
- * text: 'Hello {{firstName}}! Welcome to {{appName}}!'
1215
- * }
1216
- * }
1217
- * }
1218
- * }
1219
- * ```
1220
- */
1221
- templates?: import('../interfaces/template.interface').TemplateConfig;
1222
- }
1223
-
1224
- /**
1225
- * Phone Configuration
1226
- *
1227
- * Note: Phone verification settings have been moved to signup.phoneVerification
1228
- * This type is kept for backwards compatibility but is now empty
1229
- */
1230
- export type PhoneConfig = Record<string, never>;
1231
-
1232
- /**
1233
- * Social Login Configuration
1234
- * Configure OAuth providers for social authentication
1235
- */
1236
- export interface SocialConfig {
1237
- /**
1238
- * Google OAuth configuration
1239
- */
1240
- google?: SocialProviderConfig;
1241
-
1242
- /**
1243
- * Apple OAuth configuration
1244
- */
1245
- apple?: SocialProviderConfig;
1246
-
1247
- /**
1248
- * Facebook OAuth configuration
1249
- */
1250
- facebook?: SocialProviderConfig;
1251
- }
1252
-
1253
- /**
1254
- * Individual social provider configuration
1255
- */
1256
- export interface SocialProviderConfig {
1257
- /**
1258
- * Enable this provider
1259
- * @default false
1260
- */
1261
- enabled?: boolean;
1262
-
1263
- /**
1264
- * OAuth client ID from the provider
1265
- * Can be a single string or an array for multiple platforms (web, iOS, Android)
1266
- * Required if enabled
1267
- *
1268
- * @example
1269
- * Single client ID:
1270
- * clientId: '12345.apps.googleusercontent.com'
1271
- *
1272
- * Multiple client IDs (mobile + web):
1273
- * clientId: [
1274
- * '12345-web.apps.googleusercontent.com', // Web
1275
- * '12345-ios.apps.googleusercontent.com', // iOS
1276
- * '12345-android.apps.googleusercontent.com' // Android
1277
- * ]
1278
- */
1279
- clientId?: string | string[];
1280
-
1281
- /**
1282
- * OAuth client secret from the provider
1283
- * Required if enabled
1284
- */
1285
- clientSecret?: string;
1286
-
1287
- /**
1288
- * OAuth callback URL
1289
- * Must match the URL registered with the provider
1290
- *
1291
- * @example
1292
- * 'https://myapp.com/auth/google/callback'
1293
- */
1294
- callbackUrl?: string;
1295
-
1296
- /**
1297
- * OAuth scopes to request
1298
- * Provider-specific scopes for accessing user data
1299
- *
1300
- * @default ['openid', 'email', 'profile']
1301
- */
1302
- scopes?: string[];
1303
-
1304
- /**
1305
- * Auto-link social accounts to existing users by verified email
1306
- * If true, when a user signs in with social provider and their email
1307
- * matches an existing verified user, the accounts will be automatically linked
1308
- *
1309
- * @default true
1310
- */
1311
- autoLink?: boolean;
1312
-
1313
- /**
1314
- * Allow creating new users via social signup
1315
- * If false, only existing users can link their social accounts
1316
- *
1317
- * @default true
1318
- */
1319
- allowSignup?: boolean;
1320
- }
1321
-
1322
- /**
1323
- * Multi-Factor Authentication (MFA) Configuration
1324
- *
1325
- * Configure MFA enforcement and allowed methods for your application.
1326
- * Supports TOTP (authenticator apps), SMS, Email, and Passkeys (WebAuthn).
1327
- */
1328
- export interface MFAConfig {
1329
- /**
1330
- * Enable MFA system
1331
- * @default false
1332
- */
1333
- enabled?: boolean;
1334
-
1335
- /**
1336
- * MFA enforcement policy
1337
- *
1338
- * - 'OPTIONAL': Users can choose to enable MFA (default)
1339
- * - 'REQUIRED': All users must enable MFA within grace period
1340
- * - 'ADAPTIVE': MFA required based on risk factors (future: conditional triggers)
1341
- *
1342
- * @default 'OPTIONAL'
1343
- */
1344
- enforcement?: 'OPTIONAL' | 'REQUIRED' | 'ADAPTIVE';
1345
-
1346
- /**
1347
- * Grace period in days before MFA enforcement applies
1348
- * Only relevant when enforcement is 'REQUIRED'
1349
- * Users can login without MFA during this period
1350
- *
1351
- * @default 7
1352
- */
1353
- gracePeriod?: number;
1354
-
1355
- /**
1356
- * Allowed MFA methods
1357
- * Users can register any of these methods
1358
- *
1359
- * - 'totp': Time-based One-Time Password (Google Authenticator, Authy, etc.)
1360
- * - 'sms': SMS verification codes
1361
- * - 'email': Email verification codes
1362
- * - 'passkey': WebAuthn/FIDO2 passkeys (biometric, security keys)
1363
- *
1364
- * @default [MFAMethod.TOTP, MFAMethod.SMS, MFAMethod.EMAIL, MFAMethod.PASSKEY]
1365
- */
1366
- allowedMethods?: Array<MFADeviceMethod>;
1367
-
1368
- /**
1369
- * Require MFA for social login
1370
- *
1371
- * Controls whether MFA is required when users authenticate via
1372
- * social providers (Google, Apple, Facebook).
1373
- *
1374
- * - false: Skip MFA entirely for social login (default - common industry practice)
1375
- * Social users will NOT be required to setup or verify MFA.
1376
- * Rationale: Social providers already have strong authentication (often with 2FA),
1377
- * and OAuth flow itself provides security layer. Better UX with fewer steps.
1378
- *
1379
- * - true: Require MFA for social login (higher security)
1380
- * Social users will be required to setup and verify MFA just like password users.
1381
- * Rationale: Defense-in-depth. Even if social account is compromised,
1382
- * attacker cannot access your app without MFA.
1383
- *
1384
- * @default false
1385
- *
1386
- * @example
1387
- * ```typescript
1388
- * // Skip MFA entirely for social login (default - common practice)
1389
- * mfa: {
1390
- * requireForSocialLogin: false
1391
- * }
1392
- *
1393
- * // Require MFA for all logins including social (higher security)
1394
- * mfa: {
1395
- * requireForSocialLogin: true
1396
- * }
1397
- * ```
1398
- */
1399
- requireForSocialLogin?: boolean;
1400
-
1401
- /**
1402
- * Trusted device behavior
1403
- *
1404
- * Controls how devices are marked as trusted for MFA bypass:
1405
- * - 'never': No trusted device feature (default - most secure)
1406
- * - 'always': Automatically trust devices after successful login (no user interaction)
1407
- * - 'user_opt_in': User must explicitly opt-in via API call after login
1408
- *
1409
- * When a device is trusted:
1410
- * - Device token is stored as httpOnly cookie (web) or returned in response (mobile)
1411
- * - Device token persists across logouts and session expiry
1412
- * - Device token is independent of refresh token lifecycle
1413
- * - Trusted devices can skip MFA (if bypassMFAForTrustedDevices is enabled)
1414
- *
1415
- * @default 'never'
1416
- *
1417
- * @example
1418
- * ```typescript
1419
- * // Always trust devices automatically (best UX)
1420
- * mfa: {
1421
- * rememberDevices: 'always',
1422
- * rememberDeviceDays: 30,
1423
- * bypassMFAForTrustedDevices: true
1424
- * }
1425
- *
1426
- * // User opt-in (user controls trust)
1427
- * mfa: {
1428
- * rememberDevices: 'user_opt_in',
1429
- * rememberDeviceDays: 30,
1430
- * bypassMFAForTrustedDevices: true
1431
- * }
1432
- * ```
1433
- */
1434
- rememberDevices?: 'always' | 'user_opt_in' | 'never';
1435
-
1436
- /**
1437
- * Days to remember trusted devices
1438
- * Only relevant if rememberDevices is not 'never'
1439
- *
1440
- * @default 30
1441
- */
1442
- rememberDeviceDays?: number;
1443
-
1444
- /**
1445
- * Bypass MFA verification for trusted devices
1446
- *
1447
- * When true, trusted devices can skip MFA verification.
1448
- * This only applies when rememberDevices is not 'never' and device is marked as trusted.
1449
- *
1450
- * Note: Does NOT apply to ADAPTIVE enforcement mode, which follows its own risk-based logic.
1451
- *
1452
- * Security considerations:
1453
- * - Default false: Require MFA even for trusted devices (more secure)
1454
- * - true: Skip MFA for trusted devices (better UX, lower security)
1455
- * - Recommended: Set to false for high-security applications
1456
- *
1457
- * @default false
1458
- */
1459
- bypassMFAForTrustedDevices?: boolean;
1460
-
1461
- /**
1462
- * Issuer name for TOTP QR codes
1463
- * Displayed in authenticator apps
1464
- *
1465
- * @default 'nauth-toolkit'
1466
- */
1467
- issuer?: string;
1468
-
1469
- /**
1470
- * TOTP-specific configuration
1471
- */
1472
- totp?: TOTPConfig;
1473
-
1474
- /**
1475
- * Passkey/WebAuthn-specific configuration
1476
- */
1477
- passkey?: PasskeyConfig;
1478
-
1479
- /**
1480
- * Backup codes configuration
1481
- * Recovery codes for when users lose access to their MFA devices
1482
- */
1483
- backup?: BackupCodesConfig;
1484
-
1485
- /**
1486
- * Adaptive MFA configuration (future: conditional MFA based on risk)
1487
- * NOTE: PLACEHOLDER - Full implementation in future phase
1488
- */
1489
- adaptive?: AdaptiveMFAConfig;
1490
- }
1491
-
1492
- /**
1493
- * TOTP (Time-based One-Time Password) Configuration
1494
- * Used for authenticator apps like Google Authenticator, Authy, 1Password
1495
- */
1496
- export interface TOTPConfig {
1497
- /**
1498
- * Time window for TOTP validation
1499
- * Number of steps to check before/after current time
1500
- * Higher values are more lenient but less secure
1501
- *
1502
- * @default 1 (checks current + 1 step before/after = 3 total)
1503
- */
1504
- window?: number;
1505
-
1506
- /**
1507
- * Time step in seconds
1508
- * Standard TOTP uses 30 seconds
1509
- *
1510
- * @default 30
1511
- */
1512
- stepSeconds?: number;
1513
-
1514
- /**
1515
- * Number of digits in generated code
1516
- *
1517
- * @default 6
1518
- */
1519
- digits?: number;
1520
-
1521
- /**
1522
- * Hash algorithm for TOTP
1523
- *
1524
- * @default 'sha1' (most compatible with authenticator apps)
1525
- */
1526
- algorithm?: 'sha1' | 'sha256' | 'sha512';
1527
- }
1528
-
1529
- /**
1530
- * Passkey/WebAuthn Configuration
1531
- * Used for biometric authentication and hardware security keys
1532
- */
1533
- export interface PasskeyConfig {
1534
- /**
1535
- * Relying Party name (displayed during passkey creation)
1536
- * Should be your application name
1537
- *
1538
- * @example 'MyApp', 'Acme Corporation'
1539
- */
1540
- rpName: string;
1541
-
1542
- /**
1543
- * Relying Party ID (domain without protocol/port)
1544
- * Must match the domain serving your application
1545
- *
1546
- * @example 'myapp.com', 'example.com'
1547
- */
1548
- rpId: string;
1549
-
1550
- /**
1551
- * Expected origin for WebAuthn operations
1552
- * Must include protocol and optionally port
1553
- *
1554
- * @example 'https://myapp.com', 'http://localhost:3000'
1555
- */
1556
- origin?: string | string[];
1557
-
1558
- /**
1559
- * Timeout for passkey operations in milliseconds
1560
- *
1561
- * @default 60000 (60 seconds)
1562
- */
1563
- timeout?: number;
1564
-
1565
- /**
1566
- * Require user verification (biometric/PIN)
1567
- * 'required' | 'preferred' | 'discouraged'
1568
- *
1569
- * @default 'preferred'
1570
- */
1571
- userVerification?: 'required' | 'preferred' | 'discouraged';
1572
-
1573
- /**
1574
- * Authenticator attachment preference
1575
- * - 'platform': Built-in authenticators (Touch ID, Face ID, Windows Hello)
1576
- * - 'cross-platform': Removable authenticators (USB security keys)
1577
- *
1578
- * @default undefined (allow both)
1579
- */
1580
- authenticatorAttachment?: 'platform' | 'cross-platform';
1581
- }
1582
-
1583
- /**
1584
- * Backup/Recovery Codes Configuration
1585
- * Single-use codes for account recovery when MFA devices are unavailable
1586
- */
1587
- export interface BackupCodesConfig {
1588
- /**
1589
- * Enable backup codes
1590
- *
1591
- * @default true
1592
- */
1593
- enabled?: boolean;
1594
-
1595
- /**
1596
- * Number of backup codes to generate
1597
- *
1598
- * @default 10
1599
- */
1600
- codeCount?: number;
1601
-
1602
- /**
1603
- * Length of each backup code (characters)
1604
- *
1605
- * @default 8
1606
- */
1607
- codeLength?: number;
1608
- }
1609
-
1610
- /**
1611
- * Adaptive MFA Configuration
1612
- *
1613
- * Configures risk-based authentication that evaluates login context
1614
- * (device, IP, location) against user history to determine MFA requirements.
1615
- *
1616
- * Risk levels are evaluated in order: low → medium → high.
1617
- * Each level can have different actions (allow, require_mfa, block_signin).
1618
- *
1619
- * @example
1620
- * ```typescript
1621
- * adaptive: {
1622
- * triggers: ['new_device', 'new_ip', 'new_country'],
1623
- * riskLevels: {
1624
- * low: { maxScore: 20, action: 'allow', notifyUser: false },
1625
- * medium: { maxScore: 50, action: 'require_mfa', notifyUser: true },
1626
- * high: { maxScore: 100, action: 'block_signin', notifyUser: true }
1627
- * },
1628
- * blockedSignIn: {
1629
- * blockDuration: 60, // minutes
1630
- * message: 'Sign-in blocked due to suspicious activity'
1631
- * }
1632
- * }
1633
- * ```
1634
- */
1635
- export interface AdaptiveMFAConfig {
1636
- /**
1637
- * Risk factors that trigger MFA requirement
1638
- *
1639
- * Triggers that are evaluated during authentication:
1640
- * - 'new_device': First login from unknown device
1641
- * - 'new_ip': Login from new IP address
1642
- * - 'new_country': Login from different country
1643
- * - 'impossible_travel': Geographic distance/time anomaly
1644
- * - 'suspicious_activity': Unusual behavior patterns
1645
- *
1646
- * @default ['new_device', 'new_ip', 'new_country']
1647
- */
1648
- triggers?: Array<'new_device' | 'new_ip' | 'new_country' | 'impossible_travel' | 'suspicious_activity'>;
1649
-
1650
- /**
1651
- * Risk score threshold (0-100) to require MFA
1652
- *
1653
- * @default 50
1654
- * @deprecated Use riskLevels instead for more granular control
1655
- */
1656
- riskThreshold?: number;
1657
-
1658
- /**
1659
- * Custom risk factor weights (overrides defaults)
1660
- *
1661
- * Default weights:
1662
- * - new_device: 25
1663
- * - new_ip: 15
1664
- * - new_country: 25
1665
- * - impossible_travel: 40
1666
- * - suspicious_activity: 30
1667
- * - incomplete_location_data: 20
1668
- *
1669
- * @example
1670
- * ```typescript
1671
- * riskWeights: {
1672
- * new_device: 25,
1673
- * new_country: 30,
1674
- * incomplete_location_data: 25
1675
- * }
1676
- * ```
1677
- */
1678
- riskWeights?: Record<string, number>;
1679
-
1680
- /**
1681
- * Risk level thresholds and actions
1682
- *
1683
- * Defines score ranges and what action to take at each level.
1684
- * Scores are evaluated in order: low → medium → high.
1685
- *
1686
- * @default
1687
- * ```typescript
1688
- * {
1689
- * low: { maxScore: 20, action: 'allow', notifyUser: false },
1690
- * medium: { maxScore: 50, action: 'require_mfa', notifyUser: true },
1691
- * high: { maxScore: 100, action: 'require_mfa', notifyUser: true }
1692
- * }
1693
- * ```
1694
- *
1695
- * @example High-security configuration
1696
- * ```typescript
1697
- * riskLevels: {
1698
- * low: { maxScore: 20, action: 'allow', notifyUser: false },
1699
- * medium: { maxScore: 50, action: 'require_mfa', notifyUser: true },
1700
- * high: { maxScore: 100, action: 'block_signin', notifyUser: true }
1701
- * }
1702
- * ```
1703
- */
1704
- riskLevels?: {
1705
- low?: RiskLevelConfig;
1706
- medium?: RiskLevelConfig;
1707
- high?: RiskLevelConfig;
1708
- };
1709
-
1710
- /**
1711
- * Blocked sign-in behavior
1712
- *
1713
- * Configuration for when high-risk sign-ins are blocked.
1714
- */
1715
- blockedSignIn?: {
1716
- /**
1717
- * Duration (in minutes) to block user before allowing retry
1718
- * If not set, block is permanent until manual review
1719
- *
1720
- * @default undefined (permanent until manual review)
1721
- */
1722
- blockDuration?: number;
1723
-
1724
- /**
1725
- * Custom message to show user when blocked
1726
- *
1727
- * @default 'Sign-in blocked due to suspicious activity. Please contact support.'
1728
- */
1729
- message?: string;
1730
-
1731
- /**
1732
- * Error code to return when blocked
1733
- *
1734
- * @default 'SIGNIN_BLOCKED_HIGH_RISK'
1735
- */
1736
- errorCode?: string;
1737
- };
1738
-
1739
- /**
1740
- * Maximum realistic travel speed in km/h for impossible travel detection
1741
- *
1742
- * Used to determine if geographic distance between two locations
1743
- * is impossible given the time elapsed.
1744
- *
1745
- * @default 900 (commercial airliner speed)
1746
- */
1747
- maxTravelSpeed?: number;
1748
-
1749
- /**
1750
- * Minimum time (hours) required between country changes when city data is missing
1751
- *
1752
- * Conservative threshold for detecting suspicious country changes when
1753
- * MaxMind doesn't provide city-level data. If countries differ and either
1754
- * city is unknown, flag as suspicious if time < threshold.
1755
- *
1756
- * @default 2 (2 hours minimum between country changes)
1757
- *
1758
- * @example
1759
- * ```typescript
1760
- * countryChangeThreshold: 3 // Require 3 hours minimum between country changes
1761
- * ```
1762
- */
1763
- countryChangeThreshold?: number;
1764
-
1765
- /**
1766
- * Time window (hours) to check for suspicious activity
1767
- *
1768
- * How far back to look for suspicious audit events (failed logins,
1769
- * token reuse, etc.) when evaluating risk.
1770
- *
1771
- * @default 1 (1 hour)
1772
- */
1773
- suspiciousActivityWindow?: number;
1774
- }
1775
-
1776
- /**
1777
- * Risk level configuration
1778
- *
1779
- * Defines behavior for a specific risk level (low, medium, high).
1780
- *
1781
- * @example
1782
- * ```typescript
1783
- * {
1784
- * maxScore: 50,
1785
- * action: 'require_mfa',
1786
- * notifyUser: true
1787
- * }
1788
- * ```
1789
- */
1790
- export interface RiskLevelConfig {
1791
- /**
1792
- * Maximum risk score for this level (0-100)
1793
- *
1794
- * Scores are evaluated in order: low → medium → high.
1795
- * Example: If low.maxScore = 20 and medium.maxScore = 50:
1796
- * - Score 0-20: low
1797
- * - Score 21-50: medium
1798
- * - Score 51-100: high
1799
- */
1800
- maxScore: number;
1801
-
1802
- /**
1803
- * Action to take when risk score falls in this level
1804
- *
1805
- * - 'allow': Allow sign-in without MFA (normal flow)
1806
- * - 'require_mfa': Require MFA verification before allowing sign-in
1807
- * - 'block_signin': Block sign-in entirely (return error)
1808
- *
1809
- * @default 'allow' for low, 'require_mfa' for medium/high
1810
- */
1811
- action?: 'allow' | 'require_mfa' | 'block_signin';
1812
-
1813
- /**
1814
- * Whether to notify user of this risk event
1815
- *
1816
- * Triggers onAdaptiveMFATriggered lifecycle hook when true.
1817
- *
1818
- * @default false for low, true for medium/high
1819
- */
1820
- notifyUser?: boolean;
1821
- }
1822
-
1823
- /**
1824
- * Adaptive MFA risk event payload
1825
- *
1826
- * Rich context provided to lifecycle hooks when adaptive MFA evaluates
1827
- * a login attempt and detects risk factors.
1828
- *
1829
- * @example
1830
- * ```typescript
1831
- * onAdaptiveMFATriggered: async (payload) => {
1832
- * console.log(`Risk score: ${payload.riskScore}`);
1833
- * console.log(`Risk factors: ${payload.riskFactors.join(', ')}`);
1834
- * console.log(`Action: ${payload.action}`);
1835
- * }
1836
- * ```
1837
- */
1838
- export interface AdaptiveMFARiskEventPayload {
1839
- /**
1840
- * User being authenticated
1841
- */
1842
- user: {
1843
- sub: string;
1844
- email: string;
1845
- username?: string;
1846
- phoneNumber?: string;
1847
- };
1848
-
1849
- /**
1850
- * Risk assessment results
1851
- */
1852
- riskScore: number;
1853
- riskLevel: 'low' | 'medium' | 'high';
1854
- riskFactors: string[];
1855
-
1856
- /**
1857
- * Action that will be taken
1858
- */
1859
- action: 'allow' | 'require_mfa' | 'block_signin';
1860
-
1861
- /**
1862
- * Client context (IP, device, location, etc.)
1863
- */
1864
- clientInfo: {
1865
- ipAddress?: string;
1866
- ipCountry?: string;
1867
- ipCity?: string;
1868
- deviceId?: string;
1869
- deviceName?: string;
1870
- deviceType?: string;
1871
- userAgent?: string;
1872
- platform?: string;
1873
- browser?: string;
1874
- };
1875
-
1876
- /**
1877
- * Authentication context
1878
- */
1879
- authMethod: string; // 'password', 'google', 'apple', etc.
1880
-
1881
- /**
1882
- * Timestamp of the event
1883
- */
1884
- timestamp: Date;
1885
-
1886
- /**
1887
- * Additional metadata
1888
- */
1889
- metadata?: Record<string, unknown>;
1890
- }
1891
-
1892
- /**
1893
- * Sign-in blocked event payload
1894
- *
1895
- * Extended payload for when a sign-in is blocked due to high risk.
1896
- * Includes blocking details (duration, expiration, message).
1897
- */
1898
- export interface SignInBlockedPayload extends AdaptiveMFARiskEventPayload {
1899
- /**
1900
- * Block duration (in minutes) if temporary, undefined if permanent
1901
- */
1902
- blockDuration?: number;
1903
-
1904
- /**
1905
- * When the block will expire (if temporary)
1906
- */
1907
- blockExpiresAt?: Date;
1908
-
1909
- /**
1910
- * Message shown to user
1911
- */
1912
- message: string;
1913
- }
1914
-
1915
- /**
1916
- * Token Delivery Configuration
1917
- *
1918
- * Controls how JWT tokens are delivered to clients across different
1919
- * transports. Defaults to 'json' to remain protocol-agnostic.
1920
- */
1921
- export interface TokenDeliveryConfig {
1922
- /**
1923
- * Delivery method for tokens
1924
- * - 'json': Response body only (default)
1925
- * - 'cookies': httpOnly cookies only (browser web apps)
1926
- * - 'hybrid': Cookies first (web), then Authorization header (mobile)
1927
- *
1928
- * @default 'json'
1929
- */
1930
- method?: 'json' | 'cookies' | 'hybrid';
1931
-
1932
- /**
1933
- * Cookie name prefix for all authentication cookies
1934
- *
1935
- * All cookie names are prefixed with this value to avoid conflicts with other cookies.
1936
- * Default: 'nauth_'
1937
- *
1938
- * Cookie names generated:
1939
- * - `${prefix}access_token` (default: 'nauth_access_token')
1940
- * - `${prefix}refresh_token` (default: 'nauth_refresh_token')
1941
- * - CSRF cookie name is also prefixed (configured via security.csrf.cookieName)
1942
- *
1943
- * @default 'nauth_'
1944
- *
1945
- * @example
1946
- * ```typescript
1947
- * // Custom prefix
1948
- * cookieNamePrefix: 'myapp_'
1949
- * // Results in: 'myapp_access_token', 'myapp_refresh_token'
1950
- * ```
1951
- */
1952
- cookieNamePrefix?: string;
1953
-
1954
- /**
1955
- * Advanced cookie options (rarely needed)
1956
- *
1957
- * Smart defaults:
1958
- * - Names: 'nauth_access_token', 'nauth_refresh_token' (prefixed by cookieNamePrefix)
1959
- * - httpOnly: true (always)
1960
- * - secure: true (configurable below for localhost/dev)
1961
- * - sameSite: 'strict' (configurable below)
1962
- * - path: '/' (configurable below)
1963
- */
1964
- cookieOptions?: {
1965
- /**
1966
- * Use secure cookies (HTTPS only)
1967
- * @default true
1968
- */
1969
- secure?: boolean;
1970
-
1971
- /**
1972
- * SameSite cookie attribute
1973
- * @default 'strict'
1974
- */
1975
- sameSite?: 'strict' | 'lax' | 'none';
1976
-
1977
- /**
1978
- * Cookie path
1979
- * @default '/'
1980
- */
1981
- path?: string;
1982
-
1983
- /**
1984
- * Cookie domain (for subdomain sharing)
1985
- * @example '.myapp.com'
1986
- */
1987
- domain?: string;
1988
- };
1989
-
1990
- /**
1991
- * Strict hybrid policy (origin-based) used when method === 'hybrid'.
1992
- * webOrigins → cookies; nativeOrigins → json
1993
- */
1994
- hybridPolicy?: {
1995
- webOrigins?: string[];
1996
- nativeOrigins?: string[];
1997
- };
1998
- }
1999
-
2000
- /**
2001
- * Challenge Configuration
2002
- *
2003
- * Controls challenge session behavior for authentication challenges
2004
- * (email verification, phone verification, MFA challenges, etc.)
2005
- */
2006
- export interface ChallengeConfig {
2007
- /**
2008
- * Maximum allowed attempts per challenge session
2009
- *
2010
- * Users get this many attempts before the challenge session is invalidated.
2011
- * The (maxAttempts + 1)th failure will cause "Maximum challenge attempts exceeded" error.
2012
- *
2013
- * @default 3
2014
- *
2015
- * @example
2016
- * ```typescript
2017
- * challenge: {
2018
- * maxAttempts: 3 // User gets 3 attempts, 4th failure causes error
2019
- * }
2020
- * ```
2021
- */
2022
- maxAttempts?: number;
2023
- }
2024
-
2025
- /**
2026
- * Geolocation configuration
2027
- *
2028
- * Configures IP geolocation using MaxMind GeoIP2 database files.
2029
- * Platform-agnostic - works on all platforms where Node.js runs.
2030
- *
2031
- * @example
2032
- * ```typescript
2033
- * geoLocation: {
2034
- * maxMind: {
2035
- * licenseKey: process.env.MAXMIND_LICENSE_KEY, // Your env var name
2036
- * accountId: parseInt(process.env.MAXMIND_ACCOUNT_ID || '0'),
2037
- * // dbPath not set = uses system temp directory
2038
- * }
2039
- * }
2040
- * ```
2041
- */
2042
- export interface GeoLocationConfig {
2043
- /**
2044
- * MaxMind GeoIP2 configuration
2045
- */
2046
- maxMind?: {
2047
- /**
2048
- * Directory path where MaxMind .mmdb files are stored or should be downloaded
2049
- *
2050
- * **Usage Modes:**
2051
- * 1. **Auto-download mode**: Point to directory, toolkit downloads files
2052
- * 2. **External management mode**: Point to directory with existing files, toolkit uses them
2053
- * 3. **Default**: System temp directory (ephemeral, cleared on reboot)
2054
- *
2055
- * **Examples:**
2056
- *
2057
- * Auto-download to custom path:
2058
- * ```typescript
2059
- * maxMind: {
2060
- * dbPath: '/app/data/maxmind',
2061
- * licenseKey: '...',
2062
- * accountId: 123,
2063
- * autoDownloadOnStartup: true
2064
- * }
2065
- * ```
2066
- *
2067
- * Use existing files (consumer manages downloads):
2068
- * ```typescript
2069
- * maxMind: {
2070
- * dbPath: '/app/data/maxmind',
2071
- * // No licenseKey/accountId needed - toolkit just loads existing files
2072
- * skipDownloads: true // Disable all download functionality
2073
- * }
2074
- * ```
2075
- *
2076
- * Default temp directory (auto-download):
2077
- * ```typescript
2078
- * maxMind: {
2079
- * licenseKey: '...',
2080
- * accountId: 123
2081
- * // dbPath defaults to os.tmpdir() + '/nauth_maxmind'
2082
- * }
2083
- * ```
2084
- *
2085
- * Works on all platforms (Mac, Linux, Windows, Docker, serverless).
2086
- */
2087
- dbPath?: string;
2088
-
2089
- /**
2090
- * Skip all database downloads (consumer manages updates externally)
2091
- *
2092
- * If true, toolkit will only load existing .mmdb files from dbPath.
2093
- * Useful when:
2094
- * - Using MaxMind's geoipupdate tool
2095
- * - Managing downloads via external cron jobs
2096
- * - Databases are pre-installed in containers
2097
- * - Databases come from shared volumes/NFS
2098
- *
2099
- * When true, licenseKey and accountId are not required.
2100
- * Service will log a warning if no database files are found.
2101
- *
2102
- * @default false
2103
- */
2104
- skipDownloads?: boolean;
2105
-
2106
- /**
2107
- * MaxMind license key (required for downloading databases, not needed if skipDownloads is true)
2108
- */
2109
- licenseKey?: string;
2110
-
2111
- /**
2112
- * MaxMind account ID (required for downloading databases, not needed if skipDownloads is true)
2113
- */
2114
- accountId?: number;
2115
-
2116
- /**
2117
- * Auto-download on startup if files don't exist
2118
- * Default: false
2119
- *
2120
- * WARNING: Only enable if using distributed storage adapter (Redis/Database)
2121
- * to prevent concurrent downloads in multi-server deployments.
2122
- *
2123
- * Ignored if skipDownloads is true.
2124
- */
2125
- autoDownloadOnStartup?: boolean;
2126
-
2127
- /**
2128
- * Edition IDs to download
2129
- * Default: ['GeoLite2-City', 'GeoLite2-Country']
2130
- *
2131
- * Ignored if skipDownloads is true.
2132
- */
2133
- editions?: string[];
2134
- };
2135
- }