@nauth-toolkit/core 0.1.60 → 0.1.62
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/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +0 -22
- package/dist/bootstrap.js.map +1 -1
- package/dist/dto/change-password-request.dto.d.ts +5 -2
- package/dist/dto/change-password-request.dto.d.ts.map +1 -1
- package/dist/dto/change-password-request.dto.js +6 -1
- package/dist/dto/change-password-request.dto.js.map +1 -1
- package/dist/dto/logout-all.dto.d.ts +5 -2
- package/dist/dto/logout-all.dto.d.ts.map +1 -1
- package/dist/dto/logout-all.dto.js +6 -1
- package/dist/dto/logout-all.dto.js.map +1 -1
- package/dist/dto/refresh-token.dto.d.ts +19 -7
- package/dist/dto/refresh-token.dto.d.ts.map +1 -1
- package/dist/dto/refresh-token.dto.js +20 -6
- package/dist/dto/refresh-token.dto.js.map +1 -1
- package/dist/dto/setup-mfa.dto.d.ts +5 -2
- package/dist/dto/setup-mfa.dto.d.ts.map +1 -1
- package/dist/dto/setup-mfa.dto.js +6 -1
- package/dist/dto/setup-mfa.dto.js.map +1 -1
- package/dist/dto/update-user-attributes-request.dto.d.ts +5 -2
- package/dist/dto/update-user-attributes-request.dto.d.ts.map +1 -1
- package/dist/dto/update-user-attributes-request.dto.js +6 -1
- package/dist/dto/update-user-attributes-request.dto.js.map +1 -1
- package/dist/handlers/csrf.handler.d.ts.map +1 -1
- package/dist/handlers/csrf.handler.js +12 -1
- package/dist/handlers/csrf.handler.js.map +1 -1
- package/dist/interfaces/config.interface.d.ts +306 -76
- package/dist/interfaces/config.interface.d.ts.map +1 -1
- package/dist/interfaces/hooks.interface.d.ts +753 -7
- package/dist/interfaces/hooks.interface.d.ts.map +1 -1
- package/dist/interfaces/provider.interface.d.ts +143 -0
- package/dist/interfaces/provider.interface.d.ts.map +1 -1
- package/dist/interfaces/template.interface.d.ts +20 -43
- package/dist/interfaces/template.interface.d.ts.map +1 -1
- package/dist/interfaces/template.interface.js +8 -0
- package/dist/interfaces/template.interface.js.map +1 -1
- package/dist/internal.d.ts +5 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +7 -1
- package/dist/internal.js.map +1 -1
- package/dist/schemas/auth-config.schema.d.ts +445 -104
- package/dist/schemas/auth-config.schema.d.ts.map +1 -1
- package/dist/schemas/auth-config.schema.js +55 -8
- package/dist/schemas/auth-config.schema.js.map +1 -1
- package/dist/services/adaptive-mfa-decision.service.d.ts +25 -1
- package/dist/services/adaptive-mfa-decision.service.d.ts.map +1 -1
- package/dist/services/adaptive-mfa-decision.service.js +91 -8
- package/dist/services/adaptive-mfa-decision.service.js.map +1 -1
- package/dist/services/auth-audit.service.d.ts.map +1 -1
- package/dist/services/auth-audit.service.js +25 -4
- package/dist/services/auth-audit.service.js.map +1 -1
- package/dist/services/auth-flow-context-builder.service.d.ts.map +1 -1
- package/dist/services/auth-flow-context-builder.service.js +8 -1
- package/dist/services/auth-flow-context-builder.service.js.map +1 -1
- package/dist/services/auth-service-internal-helpers.d.ts +3 -1
- package/dist/services/auth-service-internal-helpers.d.ts.map +1 -1
- package/dist/services/auth-service-internal-helpers.js +28 -1
- package/dist/services/auth-service-internal-helpers.js.map +1 -1
- package/dist/services/auth.service.d.ts.map +1 -1
- package/dist/services/auth.service.js +84 -27
- package/dist/services/auth.service.js.map +1 -1
- package/dist/services/email-notifications.hook.d.ts +14 -0
- package/dist/services/email-notifications.hook.d.ts.map +1 -0
- package/dist/services/email-notifications.hook.js +254 -0
- package/dist/services/email-notifications.hook.js.map +1 -0
- package/dist/services/email-verification.service.d.ts.map +1 -1
- package/dist/services/email-verification.service.js +55 -0
- package/dist/services/email-verification.service.js.map +1 -1
- package/dist/services/hook-registry.service.d.ts +222 -1
- package/dist/services/hook-registry.service.d.ts.map +1 -1
- package/dist/services/hook-registry.service.js +391 -0
- package/dist/services/hook-registry.service.js.map +1 -1
- package/dist/services/mfa-base.service.d.ts +3 -1
- package/dist/services/mfa-base.service.d.ts.map +1 -1
- package/dist/services/mfa-base.service.js +70 -1
- package/dist/services/mfa-base.service.js.map +1 -1
- package/dist/services/mfa.service.d.ts +3 -1
- package/dist/services/mfa.service.d.ts.map +1 -1
- package/dist/services/mfa.service.js +32 -1
- package/dist/services/mfa.service.js.map +1 -1
- package/dist/services/password-reset.service.d.ts.map +1 -1
- package/dist/services/password-reset.service.js +5 -3
- package/dist/services/password-reset.service.js.map +1 -1
- package/dist/services/phone-verification.service.d.ts.map +1 -1
- package/dist/services/phone-verification.service.js +56 -2
- package/dist/services/phone-verification.service.js.map +1 -1
- package/dist/services/user.service.d.ts.map +1 -1
- package/dist/services/user.service.js +84 -1
- package/dist/services/user.service.js.map +1 -1
- package/dist/utils/setup/init-services.d.ts.map +1 -1
- package/dist/utils/setup/init-services.js +22 -23
- package/dist/utils/setup/init-services.js.map +1 -1
- package/dist/validators/template.validator.d.ts.map +1 -1
- package/dist/validators/template.validator.js +8 -0
- package/dist/validators/template.validator.js.map +1 -1
- package/package.json +1 -1
|
@@ -125,6 +125,69 @@ export interface SignupMetadata {
|
|
|
125
125
|
*/
|
|
126
126
|
profilePicture?: string | null;
|
|
127
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Onboarding completion source
|
|
130
|
+
*
|
|
131
|
+
* Indicates what caused onboarding to become "complete":
|
|
132
|
+
* - `signup`: Signup did not require verification (verificationMethod = 'none')
|
|
133
|
+
* - `email_verification`: Email verification completed onboarding
|
|
134
|
+
* - `phone_verification`: Phone verification completed onboarding
|
|
135
|
+
*/
|
|
136
|
+
export type OnboardingCompletionSource = 'signup' | 'email_verification' | 'phone_verification';
|
|
137
|
+
/**
|
|
138
|
+
* Onboarding completed metadata
|
|
139
|
+
*
|
|
140
|
+
* Fired exactly once when the user has satisfied the configured signup verification requirements.
|
|
141
|
+
*
|
|
142
|
+
* @remarks
|
|
143
|
+
* This is the correct lifecycle event for sending “welcome” style emails because it represents
|
|
144
|
+
* "the user can now proceed" — either immediately after signup (no verification required) or
|
|
145
|
+
* after the required verification(s) succeed.
|
|
146
|
+
*/
|
|
147
|
+
export interface OnboardingCompletedMetadata {
|
|
148
|
+
/**
|
|
149
|
+
* Configured signup verification method at the time of completion
|
|
150
|
+
*
|
|
151
|
+
* @example 'none' | 'email' | 'phone' | 'both'
|
|
152
|
+
*/
|
|
153
|
+
verificationMethod: 'none' | 'email' | 'phone' | 'both';
|
|
154
|
+
/**
|
|
155
|
+
* What completed onboarding
|
|
156
|
+
*/
|
|
157
|
+
source: OnboardingCompletionSource;
|
|
158
|
+
/**
|
|
159
|
+
* When onboarding was completed
|
|
160
|
+
*/
|
|
161
|
+
completedAt: Date;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Onboarding completed hook interface
|
|
165
|
+
*
|
|
166
|
+
* Executes actions after onboarding becomes complete (non-blocking).
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ```typescript
|
|
170
|
+
* export class WelcomeAnalyticsHook implements IOnboardingCompletedHook {
|
|
171
|
+
* async execute(user: IUser, metadata: OnboardingCompletedMetadata): Promise<void> {
|
|
172
|
+
* // Track onboarding completion event
|
|
173
|
+
* await this.analytics.track('onboarding_completed', {
|
|
174
|
+
* userSub: user.sub,
|
|
175
|
+
* verificationMethod: metadata.verificationMethod,
|
|
176
|
+
* source: metadata.source,
|
|
177
|
+
* });
|
|
178
|
+
* }
|
|
179
|
+
* }
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
export interface IOnboardingCompletedHook {
|
|
183
|
+
/**
|
|
184
|
+
* Execute onboarding completed actions
|
|
185
|
+
*
|
|
186
|
+
* @param user - User entity (IUser interface)
|
|
187
|
+
* @param metadata - Completion metadata (verification method, source, timestamp)
|
|
188
|
+
*/
|
|
189
|
+
execute(user: IUser, metadata: OnboardingCompletedMetadata): Promise<void>;
|
|
190
|
+
}
|
|
128
191
|
/**
|
|
129
192
|
* User profile update source
|
|
130
193
|
*
|
|
@@ -173,14 +236,9 @@ export interface UserProfileUpdatedMetadata {
|
|
|
173
236
|
*/
|
|
174
237
|
performedBy?: string;
|
|
175
238
|
/**
|
|
176
|
-
* Client information (IP address, user agent)
|
|
239
|
+
* Client information (IP address, user agent, location)
|
|
177
240
|
*/
|
|
178
|
-
clientInfo?:
|
|
179
|
-
ipAddress?: string;
|
|
180
|
-
userAgent?: string;
|
|
181
|
-
ipCountry?: string;
|
|
182
|
-
ipCity?: string;
|
|
183
|
-
};
|
|
241
|
+
clientInfo?: import('./client-info.interface').ClientInfo;
|
|
184
242
|
}
|
|
185
243
|
/**
|
|
186
244
|
* User profile updated hook interface
|
|
@@ -226,4 +284,692 @@ export interface IUserProfileUpdatedHook {
|
|
|
226
284
|
*/
|
|
227
285
|
execute(metadata: UserProfileUpdatedMetadata): Promise<void>;
|
|
228
286
|
}
|
|
287
|
+
/**
|
|
288
|
+
* Password changed metadata
|
|
289
|
+
*
|
|
290
|
+
* Provides context about password change events.
|
|
291
|
+
*/
|
|
292
|
+
export interface PasswordChangedMetadata {
|
|
293
|
+
/**
|
|
294
|
+
* User whose password was changed
|
|
295
|
+
*/
|
|
296
|
+
user: IUser;
|
|
297
|
+
/**
|
|
298
|
+
* How the password was changed
|
|
299
|
+
*
|
|
300
|
+
* - 'user': User changed their own password
|
|
301
|
+
* - 'admin': Admin set new password
|
|
302
|
+
* - 'reset': Password reset via forgot-password flow
|
|
303
|
+
*/
|
|
304
|
+
changedBy: 'user' | 'admin' | 'reset';
|
|
305
|
+
/**
|
|
306
|
+
* Number of sessions revoked (optional)
|
|
307
|
+
*/
|
|
308
|
+
sessionsRevoked?: number;
|
|
309
|
+
/**
|
|
310
|
+
* Client information (IP address, user agent, location)
|
|
311
|
+
*/
|
|
312
|
+
clientInfo?: import('./client-info.interface').ClientInfo;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Password changed hook interface
|
|
316
|
+
*
|
|
317
|
+
* Executes actions after password is changed (non-blocking).
|
|
318
|
+
* Errors are logged but do not affect the password change operation.
|
|
319
|
+
*
|
|
320
|
+
* @remarks
|
|
321
|
+
* This hook is triggered when:
|
|
322
|
+
* - User changes their password via `changePassword()`
|
|
323
|
+
* - Admin sets new password via `adminSetPassword()`
|
|
324
|
+
* - User completes password reset via `confirmPasswordReset()`
|
|
325
|
+
*
|
|
326
|
+
* The hook is non-blocking. If it throws an error, the error is logged
|
|
327
|
+
* but the password has already been changed when the hook is called.
|
|
328
|
+
*
|
|
329
|
+
* Use cases:
|
|
330
|
+
* - Send security alert email
|
|
331
|
+
* - Log to SIEM
|
|
332
|
+
* - Trigger account re-enrollment
|
|
333
|
+
* - Update external systems
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* ```typescript
|
|
337
|
+
* export class PasswordChangedEmailHook implements IPasswordChangedHook {
|
|
338
|
+
* async execute(metadata: PasswordChangedMetadata): Promise<void> {
|
|
339
|
+
* const { user, changedBy, sessionsRevoked } = metadata;
|
|
340
|
+
* await this.emailService.sendPasswordChangedEmail(
|
|
341
|
+
* user.email,
|
|
342
|
+
* { changedBy, sessionsRevoked }
|
|
343
|
+
* );
|
|
344
|
+
* }
|
|
345
|
+
* }
|
|
346
|
+
* ```
|
|
347
|
+
*/
|
|
348
|
+
export interface IPasswordChangedHook {
|
|
349
|
+
/**
|
|
350
|
+
* Execute password changed actions
|
|
351
|
+
*
|
|
352
|
+
* @param metadata - Password change context with user and change details
|
|
353
|
+
*/
|
|
354
|
+
execute(metadata: PasswordChangedMetadata): Promise<void>;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* MFA device removed metadata
|
|
358
|
+
*
|
|
359
|
+
* Provides context about MFA device removal events.
|
|
360
|
+
*/
|
|
361
|
+
export interface MFADeviceRemovedMetadata {
|
|
362
|
+
/**
|
|
363
|
+
* User whose MFA device was removed
|
|
364
|
+
*/
|
|
365
|
+
user: IUser;
|
|
366
|
+
/**
|
|
367
|
+
* Type of MFA device that was removed
|
|
368
|
+
*/
|
|
369
|
+
deviceType: import('../enums/mfa-method.enum').MFADeviceMethod;
|
|
370
|
+
/**
|
|
371
|
+
* Device name (optional, user-provided label)
|
|
372
|
+
*/
|
|
373
|
+
deviceName?: string;
|
|
374
|
+
/**
|
|
375
|
+
* Who removed the device
|
|
376
|
+
*
|
|
377
|
+
* - 'user': User removed their own device
|
|
378
|
+
* - 'system': System removed device (e.g., after email/phone change)
|
|
379
|
+
*/
|
|
380
|
+
removedBy: 'user' | 'system';
|
|
381
|
+
/**
|
|
382
|
+
* Reason for removal
|
|
383
|
+
*
|
|
384
|
+
* - 'email_changed': Email changed, email MFA device removed
|
|
385
|
+
* - 'phone_changed': Phone changed, SMS MFA device removed
|
|
386
|
+
* - 'user_request': User requested removal
|
|
387
|
+
* - 'admin_action': Admin removed device
|
|
388
|
+
*/
|
|
389
|
+
reason?: string;
|
|
390
|
+
/**
|
|
391
|
+
* Number of MFA devices remaining after removal
|
|
392
|
+
*/
|
|
393
|
+
remainingDeviceCount: number;
|
|
394
|
+
/**
|
|
395
|
+
* Client information (IP address, user agent, location)
|
|
396
|
+
*/
|
|
397
|
+
clientInfo?: import('./client-info.interface').ClientInfo;
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* MFA device removed hook interface
|
|
401
|
+
*
|
|
402
|
+
* Executes actions after MFA device is removed (non-blocking).
|
|
403
|
+
* Errors are logged but do not affect the removal operation.
|
|
404
|
+
*
|
|
405
|
+
* @remarks
|
|
406
|
+
* This hook is triggered when:
|
|
407
|
+
* - User removes MFA device via `removeDevices()`
|
|
408
|
+
* - System removes device due to email/phone change via `updateUserAttributes()`
|
|
409
|
+
*
|
|
410
|
+
* The hook is non-blocking. If it throws an error, the error is logged
|
|
411
|
+
* but the device has already been removed when the hook is called.
|
|
412
|
+
*
|
|
413
|
+
* Use cases:
|
|
414
|
+
* - Send security alert email
|
|
415
|
+
* - Log to SIEM
|
|
416
|
+
* - Warn if last device removed
|
|
417
|
+
* - Update external systems
|
|
418
|
+
*
|
|
419
|
+
* @example
|
|
420
|
+
* ```typescript
|
|
421
|
+
* export class MFADeviceRemovedAlertHook implements IMFADeviceRemovedHook {
|
|
422
|
+
* async execute(metadata: MFADeviceRemovedMetadata): Promise<void> {
|
|
423
|
+
* const { user, deviceType, remainingDeviceCount } = metadata;
|
|
424
|
+
* if (remainingDeviceCount === 0) {
|
|
425
|
+
* await this.emailService.sendMFADeviceRemovedEmail(
|
|
426
|
+
* user.email,
|
|
427
|
+
* { deviceType, warning: 'No MFA devices remaining' }
|
|
428
|
+
* );
|
|
429
|
+
* }
|
|
430
|
+
* }
|
|
431
|
+
* }
|
|
432
|
+
* ```
|
|
433
|
+
*/
|
|
434
|
+
export interface IMFADeviceRemovedHook {
|
|
435
|
+
/**
|
|
436
|
+
* Execute MFA device removed actions
|
|
437
|
+
*
|
|
438
|
+
* @param metadata - Device removal context with user and device details
|
|
439
|
+
*/
|
|
440
|
+
execute(metadata: MFADeviceRemovedMetadata): Promise<void>;
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Adaptive MFA risk detected metadata
|
|
444
|
+
*
|
|
445
|
+
* Provides context about adaptive MFA risk evaluation events.
|
|
446
|
+
*/
|
|
447
|
+
export interface AdaptiveMFARiskDetectedMetadata {
|
|
448
|
+
/**
|
|
449
|
+
* User being authenticated
|
|
450
|
+
*/
|
|
451
|
+
user: IUser;
|
|
452
|
+
/**
|
|
453
|
+
* Risk score (0-100)
|
|
454
|
+
*/
|
|
455
|
+
riskScore: number;
|
|
456
|
+
/**
|
|
457
|
+
* Risk level classification
|
|
458
|
+
*/
|
|
459
|
+
riskLevel: 'low' | 'medium' | 'high';
|
|
460
|
+
/**
|
|
461
|
+
* Detected risk factors
|
|
462
|
+
*/
|
|
463
|
+
riskFactors: import('../enums/risk-factor.enum').RiskFactor[];
|
|
464
|
+
/**
|
|
465
|
+
* Action taken based on risk level
|
|
466
|
+
*
|
|
467
|
+
* - 'allow': No MFA required
|
|
468
|
+
* - 'require_mfa': MFA verification required
|
|
469
|
+
* - 'block_signin': Sign-in blocked
|
|
470
|
+
*/
|
|
471
|
+
action: 'allow' | 'require_mfa' | 'block_signin';
|
|
472
|
+
/**
|
|
473
|
+
* Authentication method used
|
|
474
|
+
*/
|
|
475
|
+
authMethod: string;
|
|
476
|
+
/**
|
|
477
|
+
* Client information (IP address, user agent, location)
|
|
478
|
+
*/
|
|
479
|
+
clientInfo: import('./client-info.interface').ClientInfo;
|
|
480
|
+
/**
|
|
481
|
+
* Event timestamp
|
|
482
|
+
*/
|
|
483
|
+
timestamp: Date;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Adaptive MFA risk detected hook interface
|
|
487
|
+
*
|
|
488
|
+
* Executes actions when adaptive MFA evaluates risk (non-blocking).
|
|
489
|
+
* Only triggered when notifyUser is true in risk level config.
|
|
490
|
+
* Errors are logged but do not affect authentication flow.
|
|
491
|
+
*
|
|
492
|
+
* @remarks
|
|
493
|
+
* This hook is triggered when:
|
|
494
|
+
* - Adaptive MFA evaluates login and detects risk factors
|
|
495
|
+
* - Risk level configuration has `notifyUser: true`
|
|
496
|
+
*
|
|
497
|
+
* The hook is non-blocking. If it throws an error, the error is logged
|
|
498
|
+
* but authentication flow continues normally.
|
|
499
|
+
*
|
|
500
|
+
* Use cases:
|
|
501
|
+
* - Send risk alert email
|
|
502
|
+
* - Log to SIEM
|
|
503
|
+
* - Trigger additional verification
|
|
504
|
+
* - Update fraud detection systems
|
|
505
|
+
*
|
|
506
|
+
* @example
|
|
507
|
+
* ```typescript
|
|
508
|
+
* export class AdaptiveMFARiskAlertHook implements IAdaptiveMFARiskDetectedHook {
|
|
509
|
+
* async execute(metadata: AdaptiveMFARiskDetectedMetadata): Promise<void> {
|
|
510
|
+
* const { user, riskScore, riskLevel, riskFactors } = metadata;
|
|
511
|
+
* if (riskLevel === 'high') {
|
|
512
|
+
* await this.emailService.sendRiskAlertEmail(
|
|
513
|
+
* user.email,
|
|
514
|
+
* { riskScore, riskFactors }
|
|
515
|
+
* );
|
|
516
|
+
* }
|
|
517
|
+
* }
|
|
518
|
+
* }
|
|
519
|
+
* ```
|
|
520
|
+
*/
|
|
521
|
+
export interface IAdaptiveMFARiskDetectedHook {
|
|
522
|
+
/**
|
|
523
|
+
* Execute adaptive MFA risk detected actions
|
|
524
|
+
*
|
|
525
|
+
* @param metadata - Risk evaluation context with user and risk details
|
|
526
|
+
*/
|
|
527
|
+
execute(metadata: AdaptiveMFARiskDetectedMetadata): Promise<void>;
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Account status changed metadata
|
|
531
|
+
*
|
|
532
|
+
* Provides context about account enable/disable events.
|
|
533
|
+
*/
|
|
534
|
+
export interface AccountStatusChangedMetadata {
|
|
535
|
+
/**
|
|
536
|
+
* User whose account status changed
|
|
537
|
+
*/
|
|
538
|
+
user: IUser;
|
|
539
|
+
/**
|
|
540
|
+
* New account status
|
|
541
|
+
*
|
|
542
|
+
* - 'disabled': Account was disabled
|
|
543
|
+
* - 'enabled': Account was enabled
|
|
544
|
+
*/
|
|
545
|
+
status: 'disabled' | 'enabled';
|
|
546
|
+
/**
|
|
547
|
+
* Reason for status change
|
|
548
|
+
*/
|
|
549
|
+
reason?: string;
|
|
550
|
+
/**
|
|
551
|
+
* Admin who performed the action (admin sub)
|
|
552
|
+
*/
|
|
553
|
+
performedBy?: string;
|
|
554
|
+
/**
|
|
555
|
+
* Number of sessions revoked (for disable action)
|
|
556
|
+
*/
|
|
557
|
+
revokedSessions?: number;
|
|
558
|
+
/**
|
|
559
|
+
* Client information (IP address, user agent, location)
|
|
560
|
+
*/
|
|
561
|
+
clientInfo?: import('./client-info.interface').ClientInfo;
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Account status changed hook interface
|
|
565
|
+
*
|
|
566
|
+
* Executes actions after account is enabled or disabled (non-blocking).
|
|
567
|
+
* Errors are logged but do not affect the status change operation.
|
|
568
|
+
*
|
|
569
|
+
* @remarks
|
|
570
|
+
* This hook is triggered when:
|
|
571
|
+
* - Admin disables user account via `disableUser()`
|
|
572
|
+
* - Admin enables user account via `enableUser()`
|
|
573
|
+
*
|
|
574
|
+
* The hook is non-blocking. If it throws an error, the error is logged
|
|
575
|
+
* but the account status has already been changed when the hook is called.
|
|
576
|
+
*
|
|
577
|
+
* Use cases:
|
|
578
|
+
* - Notify user of account status change
|
|
579
|
+
* - Log to compliance system
|
|
580
|
+
* - Trigger CRM/support workflows
|
|
581
|
+
* - Update external systems
|
|
582
|
+
*
|
|
583
|
+
* @example
|
|
584
|
+
* ```typescript
|
|
585
|
+
* export class AccountStatusNotificationHook implements IAccountStatusChangedHook {
|
|
586
|
+
* async execute(metadata: AccountStatusChangedMetadata): Promise<void> {
|
|
587
|
+
* const { user, status, reason } = metadata;
|
|
588
|
+
* if (status === 'disabled') {
|
|
589
|
+
* await this.emailService.sendAccountDisabledEmail(
|
|
590
|
+
* user.email,
|
|
591
|
+
* { reason }
|
|
592
|
+
* );
|
|
593
|
+
* }
|
|
594
|
+
* }
|
|
595
|
+
* }
|
|
596
|
+
* ```
|
|
597
|
+
*/
|
|
598
|
+
export interface IAccountStatusChangedHook {
|
|
599
|
+
/**
|
|
600
|
+
* Execute account status changed actions
|
|
601
|
+
*
|
|
602
|
+
* @param metadata - Status change context with user and change details
|
|
603
|
+
*/
|
|
604
|
+
execute(metadata: AccountStatusChangedMetadata): Promise<void>;
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* Email changed metadata
|
|
608
|
+
*
|
|
609
|
+
* Provides context about email change events.
|
|
610
|
+
*/
|
|
611
|
+
export interface EmailChangedMetadata {
|
|
612
|
+
/**
|
|
613
|
+
* User whose email was changed
|
|
614
|
+
*/
|
|
615
|
+
user: IUser;
|
|
616
|
+
/**
|
|
617
|
+
* Old email address (before change)
|
|
618
|
+
*/
|
|
619
|
+
oldEmail: string;
|
|
620
|
+
/**
|
|
621
|
+
* New email address (after change)
|
|
622
|
+
*/
|
|
623
|
+
newEmail: string;
|
|
624
|
+
/**
|
|
625
|
+
* Source of the email change
|
|
626
|
+
*/
|
|
627
|
+
updateSource: UserProfileUpdateSource;
|
|
628
|
+
/**
|
|
629
|
+
* Number of MFA devices deactivated due to email change
|
|
630
|
+
*/
|
|
631
|
+
deactivatedMFADevices?: number;
|
|
632
|
+
/**
|
|
633
|
+
* Client information (IP address, user agent, location)
|
|
634
|
+
*/
|
|
635
|
+
clientInfo?: import('./client-info.interface').ClientInfo;
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* Email changed hook interface
|
|
639
|
+
*
|
|
640
|
+
* Executes actions after email address is changed (non-blocking).
|
|
641
|
+
* Errors are logged but do not affect the email change operation.
|
|
642
|
+
*
|
|
643
|
+
* @remarks
|
|
644
|
+
* This hook is triggered when:
|
|
645
|
+
* - User changes email via `updateUserAttributes()`
|
|
646
|
+
*
|
|
647
|
+
* The hook is non-blocking. If it throws an error, the error is logged
|
|
648
|
+
* but the email has already been changed when the hook is called.
|
|
649
|
+
*
|
|
650
|
+
* **Important:** This hook triggers TWO emails for security:
|
|
651
|
+
* 1. Alert to OLD email address (security notification)
|
|
652
|
+
* 2. Confirmation to NEW email address
|
|
653
|
+
*
|
|
654
|
+
* Use cases:
|
|
655
|
+
* - Send security alert to old email
|
|
656
|
+
* - Send confirmation to new email
|
|
657
|
+
* - Log to audit system
|
|
658
|
+
* - Update external systems
|
|
659
|
+
*
|
|
660
|
+
* @example
|
|
661
|
+
* ```typescript
|
|
662
|
+
* export class EmailChangedNotificationHook implements IEmailChangedHook {
|
|
663
|
+
* async execute(metadata: EmailChangedMetadata): Promise<void> {
|
|
664
|
+
* const { oldEmail, newEmail, deactivatedMFADevices } = metadata;
|
|
665
|
+
*
|
|
666
|
+
* // Alert to old email
|
|
667
|
+
* await this.emailService.sendEmailChangedAlertEmail(
|
|
668
|
+
* oldEmail,
|
|
669
|
+
* { newEmail, deactivatedMFADevices }
|
|
670
|
+
* );
|
|
671
|
+
*
|
|
672
|
+
* // Confirmation to new email
|
|
673
|
+
* await this.emailService.sendEmailChangedConfirmationEmail(
|
|
674
|
+
* newEmail
|
|
675
|
+
* );
|
|
676
|
+
* }
|
|
677
|
+
* }
|
|
678
|
+
* ```
|
|
679
|
+
*/
|
|
680
|
+
export interface IEmailChangedHook {
|
|
681
|
+
/**
|
|
682
|
+
* Execute email changed actions
|
|
683
|
+
*
|
|
684
|
+
* @param metadata - Email change context with old and new addresses
|
|
685
|
+
*/
|
|
686
|
+
execute(metadata: EmailChangedMetadata): Promise<void>;
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Account locked metadata
|
|
690
|
+
*
|
|
691
|
+
* Provides context about account lockout events.
|
|
692
|
+
*/
|
|
693
|
+
export interface AccountLockedMetadata {
|
|
694
|
+
/**
|
|
695
|
+
* User whose account was locked
|
|
696
|
+
*/
|
|
697
|
+
user: IUser;
|
|
698
|
+
/**
|
|
699
|
+
* Reason for lockout
|
|
700
|
+
*/
|
|
701
|
+
reason: string;
|
|
702
|
+
/**
|
|
703
|
+
* Type of lock
|
|
704
|
+
*
|
|
705
|
+
* - 'temporary': Temporary lockout (auto-unlocks)
|
|
706
|
+
* - 'permanent': Permanent lock (requires admin intervention)
|
|
707
|
+
*/
|
|
708
|
+
lockType: 'temporary' | 'permanent';
|
|
709
|
+
/**
|
|
710
|
+
* Lock duration in seconds (for temporary locks)
|
|
711
|
+
*/
|
|
712
|
+
lockDuration?: number;
|
|
713
|
+
/**
|
|
714
|
+
* When the lock expires (for temporary locks)
|
|
715
|
+
*/
|
|
716
|
+
lockedUntil?: Date;
|
|
717
|
+
/**
|
|
718
|
+
* IP address that triggered the lockout
|
|
719
|
+
*/
|
|
720
|
+
ipAddress?: string;
|
|
721
|
+
/**
|
|
722
|
+
* Number of failed attempts that triggered lockout
|
|
723
|
+
*/
|
|
724
|
+
failedAttempts?: number;
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* Account locked hook interface
|
|
728
|
+
*
|
|
729
|
+
* Executes actions after account is locked (non-blocking).
|
|
730
|
+
* Errors are logged but do not affect the lockout operation.
|
|
731
|
+
*
|
|
732
|
+
* @remarks
|
|
733
|
+
* This hook is triggered when:
|
|
734
|
+
* - Account lockout threshold is reached via `handleFailedLogin()`
|
|
735
|
+
*
|
|
736
|
+
* The hook is non-blocking. If it throws an error, the error is logged
|
|
737
|
+
* but the account has already been locked when the hook is called.
|
|
738
|
+
*
|
|
739
|
+
* Use cases:
|
|
740
|
+
* - Notify user of lockout
|
|
741
|
+
* - Log to security system
|
|
742
|
+
* - Trigger fraud detection
|
|
743
|
+
* - Alert admins for high-risk lockouts
|
|
744
|
+
*
|
|
745
|
+
* @example
|
|
746
|
+
* ```typescript
|
|
747
|
+
* export class AccountLockedNotificationHook implements IAccountLockedHook {
|
|
748
|
+
* async execute(metadata: AccountLockedMetadata): Promise<void> {
|
|
749
|
+
* const { user, reason, lockDuration } = metadata;
|
|
750
|
+
* await this.emailService.sendAccountLockedEmail(
|
|
751
|
+
* user.email,
|
|
752
|
+
* { reason, lockDuration }
|
|
753
|
+
* );
|
|
754
|
+
* }
|
|
755
|
+
* }
|
|
756
|
+
* ```
|
|
757
|
+
*/
|
|
758
|
+
export interface IAccountLockedHook {
|
|
759
|
+
/**
|
|
760
|
+
* Execute account locked actions
|
|
761
|
+
*
|
|
762
|
+
* @param metadata - Lockout context with user and lock details
|
|
763
|
+
*/
|
|
764
|
+
execute(metadata: AccountLockedMetadata): Promise<void>;
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Sessions revoked metadata
|
|
768
|
+
*
|
|
769
|
+
* Provides context about session revocation events.
|
|
770
|
+
*/
|
|
771
|
+
export interface SessionsRevokedMetadata {
|
|
772
|
+
/**
|
|
773
|
+
* User whose sessions were revoked
|
|
774
|
+
*/
|
|
775
|
+
user: IUser;
|
|
776
|
+
/**
|
|
777
|
+
* Number of sessions revoked
|
|
778
|
+
*/
|
|
779
|
+
revokedCount: number;
|
|
780
|
+
/**
|
|
781
|
+
* Reason for revocation
|
|
782
|
+
*/
|
|
783
|
+
reason: string;
|
|
784
|
+
/**
|
|
785
|
+
* Who initiated the revocation
|
|
786
|
+
*
|
|
787
|
+
* - 'user': User revoked their own sessions
|
|
788
|
+
* - 'admin': Admin revoked sessions
|
|
789
|
+
* - 'system': System revoked sessions (e.g., password change)
|
|
790
|
+
*/
|
|
791
|
+
initiatedBy: 'user' | 'admin' | 'system';
|
|
792
|
+
/**
|
|
793
|
+
* Trigger event (optional)
|
|
794
|
+
*
|
|
795
|
+
* - 'password_changed': Password change triggered revocation
|
|
796
|
+
* - 'account_disabled': Account disable triggered revocation
|
|
797
|
+
* - 'user_request': User manually revoked sessions
|
|
798
|
+
*/
|
|
799
|
+
triggerEvent?: string;
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* Sessions revoked hook interface
|
|
803
|
+
*
|
|
804
|
+
* Executes actions after sessions are revoked (non-blocking).
|
|
805
|
+
* Errors are logged but do not affect the revocation operation.
|
|
806
|
+
*
|
|
807
|
+
* @remarks
|
|
808
|
+
* This hook is triggered when:
|
|
809
|
+
* - Sessions are revoked via `revokeAllUserSessions()` when NOT user-initiated
|
|
810
|
+
*
|
|
811
|
+
* The hook is non-blocking. If it throws an error, the error is logged
|
|
812
|
+
* but the sessions have already been revoked when the hook is called.
|
|
813
|
+
*
|
|
814
|
+
* **Note:** Hook is NOT triggered for user-initiated revocations (when user
|
|
815
|
+
* explicitly logs out or revokes sessions) to avoid notification spam.
|
|
816
|
+
*
|
|
817
|
+
* Use cases:
|
|
818
|
+
* - Send security alert about forced logout
|
|
819
|
+
* - Log to security system
|
|
820
|
+
* - Update external systems
|
|
821
|
+
*
|
|
822
|
+
* @example
|
|
823
|
+
* ```typescript
|
|
824
|
+
* export class SessionsRevokedAlertHook implements ISessionsRevokedHook {
|
|
825
|
+
* async execute(metadata: SessionsRevokedMetadata): Promise<void> {
|
|
826
|
+
* const { user, revokedCount, reason } = metadata;
|
|
827
|
+
* if (reason === 'password_changed') {
|
|
828
|
+
* await this.emailService.sendSessionsRevokedEmail(
|
|
829
|
+
* user.email,
|
|
830
|
+
* { revokedCount, reason }
|
|
831
|
+
* );
|
|
832
|
+
* }
|
|
833
|
+
* }
|
|
834
|
+
* }
|
|
835
|
+
* ```
|
|
836
|
+
*/
|
|
837
|
+
export interface ISessionsRevokedHook {
|
|
838
|
+
/**
|
|
839
|
+
* Execute sessions revoked actions
|
|
840
|
+
*
|
|
841
|
+
* @param metadata - Revocation context with user and session details
|
|
842
|
+
*/
|
|
843
|
+
execute(metadata: SessionsRevokedMetadata): Promise<void>;
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* MFA first enabled metadata
|
|
847
|
+
*
|
|
848
|
+
* Provides context about first MFA device enrollment.
|
|
849
|
+
*/
|
|
850
|
+
export interface MFAFirstEnabledMetadata {
|
|
851
|
+
/**
|
|
852
|
+
* User who enabled their first MFA device
|
|
853
|
+
*/
|
|
854
|
+
user: IUser;
|
|
855
|
+
/**
|
|
856
|
+
* Type of first MFA device
|
|
857
|
+
*/
|
|
858
|
+
firstMethod: import('../enums/mfa-method.enum').MFADeviceMethod;
|
|
859
|
+
/**
|
|
860
|
+
* Device name (optional, user-provided label)
|
|
861
|
+
*/
|
|
862
|
+
deviceName?: string;
|
|
863
|
+
/**
|
|
864
|
+
* When MFA was first enforced for this user
|
|
865
|
+
*/
|
|
866
|
+
enforcedAt: Date;
|
|
867
|
+
/**
|
|
868
|
+
* Client information (IP address, user agent, location)
|
|
869
|
+
*/
|
|
870
|
+
clientInfo?: import('./client-info.interface').ClientInfo;
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* MFA first enabled hook interface
|
|
874
|
+
*
|
|
875
|
+
* Executes actions when user enables their first MFA device (non-blocking).
|
|
876
|
+
* Errors are logged but do not affect the MFA enrollment operation.
|
|
877
|
+
*
|
|
878
|
+
* @remarks
|
|
879
|
+
* This hook is triggered when:
|
|
880
|
+
* - User enables their first MFA device via `enableMFAForUser()` when `isFirstDevice = true`
|
|
881
|
+
*
|
|
882
|
+
* The hook is non-blocking. If it throws an error, the error is logged
|
|
883
|
+
* but the MFA device has already been enabled when the hook is called.
|
|
884
|
+
*
|
|
885
|
+
* Use cases:
|
|
886
|
+
* - Send confirmation email
|
|
887
|
+
* - Log to audit system
|
|
888
|
+
* - Update onboarding status
|
|
889
|
+
* - Update external systems
|
|
890
|
+
*
|
|
891
|
+
* @example
|
|
892
|
+
* ```typescript
|
|
893
|
+
* export class MFAFirstEnabledConfirmationHook implements IMFAFirstEnabledHook {
|
|
894
|
+
* async execute(metadata: MFAFirstEnabledMetadata): Promise<void> {
|
|
895
|
+
* const { user, firstMethod } = metadata;
|
|
896
|
+
* await this.emailService.sendMFAFirstEnabledEmail(
|
|
897
|
+
* user.email,
|
|
898
|
+
* { method: firstMethod }
|
|
899
|
+
* );
|
|
900
|
+
* }
|
|
901
|
+
* }
|
|
902
|
+
* ```
|
|
903
|
+
*/
|
|
904
|
+
export interface IMFAFirstEnabledHook {
|
|
905
|
+
/**
|
|
906
|
+
* Execute MFA first enabled actions
|
|
907
|
+
*
|
|
908
|
+
* @param metadata - MFA enrollment context with user and device details
|
|
909
|
+
*/
|
|
910
|
+
execute(metadata: MFAFirstEnabledMetadata): Promise<void>;
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* MFA method added metadata
|
|
914
|
+
*
|
|
915
|
+
* Provides context when a user adds an additional MFA method (e.g., adding Passkey
|
|
916
|
+
* after already having TOTP enabled).
|
|
917
|
+
*/
|
|
918
|
+
export interface MFAMethodAddedMetadata {
|
|
919
|
+
/**
|
|
920
|
+
* User who added an MFA method
|
|
921
|
+
*/
|
|
922
|
+
user: IUser;
|
|
923
|
+
/**
|
|
924
|
+
* MFA method that was added
|
|
925
|
+
*/
|
|
926
|
+
method: import('../enums/mfa-method.enum').MFADeviceMethod;
|
|
927
|
+
/**
|
|
928
|
+
* Device name (optional, user-provided label)
|
|
929
|
+
*/
|
|
930
|
+
deviceName?: string;
|
|
931
|
+
/**
|
|
932
|
+
* Whether this method addition is also the user's first MFA method
|
|
933
|
+
*/
|
|
934
|
+
isFirstMethod: boolean;
|
|
935
|
+
/**
|
|
936
|
+
* Enabled MFA methods after the change
|
|
937
|
+
*/
|
|
938
|
+
enabledMethods: import('../enums/mfa-method.enum').MFADeviceMethod[];
|
|
939
|
+
/**
|
|
940
|
+
* Event timestamp
|
|
941
|
+
*/
|
|
942
|
+
timestamp: Date;
|
|
943
|
+
/**
|
|
944
|
+
* Client information (IP address, user agent, location)
|
|
945
|
+
*/
|
|
946
|
+
clientInfo?: import('./client-info.interface').ClientInfo;
|
|
947
|
+
}
|
|
948
|
+
/**
|
|
949
|
+
* MFA method added hook interface
|
|
950
|
+
*
|
|
951
|
+
* Executes actions after a user adds an MFA method (non-blocking).
|
|
952
|
+
* Errors are logged but do not affect the MFA enrollment operation.
|
|
953
|
+
*
|
|
954
|
+
* @example
|
|
955
|
+
* ```typescript
|
|
956
|
+
* export class MFAMethodAddedNotificationHook implements IMFAMethodAddedHook {
|
|
957
|
+
* async execute(metadata: MFAMethodAddedMetadata): Promise<void> {
|
|
958
|
+
* const { user, method, enabledMethods } = metadata;
|
|
959
|
+
* await this.emailService.sendMFAMethodAddedEmail(user.email, {
|
|
960
|
+
* method,
|
|
961
|
+
* enabledMethods,
|
|
962
|
+
* });
|
|
963
|
+
* }
|
|
964
|
+
* }
|
|
965
|
+
* ```
|
|
966
|
+
*/
|
|
967
|
+
export interface IMFAMethodAddedHook {
|
|
968
|
+
/**
|
|
969
|
+
* Execute MFA method added actions
|
|
970
|
+
*
|
|
971
|
+
* @param metadata - MFA method addition context
|
|
972
|
+
*/
|
|
973
|
+
execute(metadata: MFAMethodAddedMetadata): Promise<void>;
|
|
974
|
+
}
|
|
229
975
|
//# sourceMappingURL=hooks.interface.d.ts.map
|