@nauth-toolkit/core 0.1.34 → 0.1.36
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 +1 -1
- package/dist/bootstrap.js.map +1 -1
- package/dist/dto/login.dto.js +1 -1
- package/dist/enums/error-codes.enum.d.ts +7 -0
- package/dist/enums/error-codes.enum.d.ts.map +1 -1
- package/dist/enums/error-codes.enum.js +7 -0
- package/dist/enums/error-codes.enum.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces/config.interface.d.ts +3 -146
- package/dist/interfaces/config.interface.d.ts.map +1 -1
- package/dist/interfaces/hooks.interface.d.ts +194 -0
- package/dist/interfaces/hooks.interface.d.ts.map +1 -0
- package/dist/interfaces/hooks.interface.js +12 -0
- package/dist/interfaces/hooks.interface.js.map +1 -0
- package/dist/interfaces/index.d.ts +1 -0
- package/dist/interfaces/index.d.ts.map +1 -1
- package/dist/interfaces/index.js +1 -0
- package/dist/interfaces/index.js.map +1 -1
- package/dist/internal.d.ts +5 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +10 -1
- package/dist/internal.js.map +1 -1
- package/dist/schemas/auth-config.schema.d.ts +0 -126
- package/dist/schemas/auth-config.schema.d.ts.map +1 -1
- package/dist/schemas/auth-config.schema.js +1 -15
- package/dist/schemas/auth-config.schema.js.map +1 -1
- package/dist/services/adaptive-mfa-decision.service.d.ts.map +1 -1
- package/dist/services/adaptive-mfa-decision.service.js +2 -32
- package/dist/services/adaptive-mfa-decision.service.js.map +1 -1
- package/dist/services/auth.service.d.ts +3 -1
- package/dist/services/auth.service.d.ts.map +1 -1
- package/dist/services/auth.service.js +75 -38
- package/dist/services/auth.service.js.map +1 -1
- package/dist/services/hook-registry.service.d.ts +125 -0
- package/dist/services/hook-registry.service.d.ts.map +1 -0
- package/dist/services/hook-registry.service.js +177 -0
- package/dist/services/hook-registry.service.js.map +1 -0
- package/dist/services/social-auth-base.service.d.ts +3 -1
- package/dist/services/social-auth-base.service.d.ts.map +1 -1
- package/dist/services/social-auth-base.service.js +24 -1
- package/dist/services/social-auth-base.service.js.map +1 -1
- package/dist/services/social-redirect.handler.d.ts +12 -1
- package/dist/services/social-redirect.handler.d.ts.map +1 -1
- package/dist/services/social-redirect.handler.js +26 -1
- package/dist/services/social-redirect.handler.js.map +1 -1
- package/dist/utils/setup/init-services.d.ts +2 -1
- package/dist/utils/setup/init-services.d.ts.map +1 -1
- package/dist/utils/setup/init-services.js +4 -1
- package/dist/utils/setup/init-services.js.map +1 -1
- package/dist/utils/setup/init-social.d.ts +1 -1
- package/dist/utils/setup/init-social.d.ts.map +1 -1
- package/dist/utils/setup/init-social.js +4 -4
- package/dist/utils/setup/init-social.js.map +1 -1
- package/package.json +1 -1
|
@@ -92,6 +92,7 @@ class AuthService {
|
|
|
92
92
|
accountLockoutStorage;
|
|
93
93
|
config;
|
|
94
94
|
logger;
|
|
95
|
+
hookRegistry;
|
|
95
96
|
auditService;
|
|
96
97
|
phoneVerificationService;
|
|
97
98
|
mfaService;
|
|
@@ -105,7 +106,7 @@ class AuthService {
|
|
|
105
106
|
challengeSessionRepository;
|
|
106
107
|
authAuditRepository;
|
|
107
108
|
trustedDeviceRepository;
|
|
108
|
-
constructor(userRepository, loginAttemptRepository, passwordService, jwtService, sessionService, challengeService, challengeHelper, emailVerificationService, clientInfoService, accountLockoutStorage, config, logger, auditService, // Optional - audit trail service (enabled via config.auditLogs.enabled)
|
|
109
|
+
constructor(userRepository, loginAttemptRepository, passwordService, jwtService, sessionService, challengeService, challengeHelper, emailVerificationService, clientInfoService, accountLockoutStorage, config, logger, hookRegistry, auditService, // Optional - audit trail service (enabled via config.auditLogs.enabled)
|
|
109
110
|
phoneVerificationService, // Optional - only available when SMS provider is configured
|
|
110
111
|
mfaService, // Optional - available when MFA modules are imported
|
|
111
112
|
mfaDeviceRepository, // Optional - available when MFA modules are imported
|
|
@@ -130,6 +131,7 @@ class AuthService {
|
|
|
130
131
|
this.accountLockoutStorage = accountLockoutStorage;
|
|
131
132
|
this.config = config;
|
|
132
133
|
this.logger = logger;
|
|
134
|
+
this.hookRegistry = hookRegistry;
|
|
133
135
|
this.auditService = auditService;
|
|
134
136
|
this.phoneVerificationService = phoneVerificationService;
|
|
135
137
|
this.mfaService = mfaService;
|
|
@@ -224,6 +226,12 @@ class AuthService {
|
|
|
224
226
|
}
|
|
225
227
|
// Hash password
|
|
226
228
|
const passwordHash = await this.passwordService.hashPassword(dto.password);
|
|
229
|
+
// ============================================================================
|
|
230
|
+
// Lifecycle Hook: preSignup
|
|
231
|
+
// ============================================================================
|
|
232
|
+
// Execute preSignup hook before user creation
|
|
233
|
+
// Hook can throw NAuthException with PRESIGNUP_FAILED to block signup with custom message
|
|
234
|
+
await this.hookRegistry.executePreSignup(dto, 'password', undefined, false);
|
|
227
235
|
// Determine verification requirements based on verification method
|
|
228
236
|
const verificationMethod = this.config.signup?.verificationMethod;
|
|
229
237
|
// Validate required fields based on verification method
|
|
@@ -314,10 +322,15 @@ class AuthService {
|
|
|
314
322
|
// All verification codes are sent when challenges are created (in AuthChallengeHelperService.createChallengeResponse)
|
|
315
323
|
// This ensures proper sequential flow: email code first, then phone code after email is verified
|
|
316
324
|
// This prevents user confusion from receiving multiple codes at once
|
|
317
|
-
//
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
325
|
+
// ============================================================================
|
|
326
|
+
// Lifecycle Hook: afterSignup
|
|
327
|
+
// ============================================================================
|
|
328
|
+
// Execute afterSignup hook immediately after account creation (non-blocking)
|
|
329
|
+
await this.hookRegistry.executeAfterSignup(savedUser, {
|
|
330
|
+
requiresVerification: verificationMethod !== 'none',
|
|
331
|
+
signupType: 'password',
|
|
332
|
+
adminSignup: false,
|
|
333
|
+
});
|
|
321
334
|
// ============================================================================
|
|
322
335
|
// Challenge System: Determine if user needs to complete challenges
|
|
323
336
|
// ============================================================================
|
|
@@ -441,6 +454,12 @@ class AuthService {
|
|
|
441
454
|
// Hash password
|
|
442
455
|
passwordHash = await this.passwordService.hashPassword(dto.password);
|
|
443
456
|
}
|
|
457
|
+
// ============================================================================
|
|
458
|
+
// Lifecycle Hook: preSignup
|
|
459
|
+
// ============================================================================
|
|
460
|
+
// Execute preSignup hook before user creation (admin signup)
|
|
461
|
+
// Hook can throw NAuthException with PRESIGNUP_FAILED to block signup with custom message
|
|
462
|
+
await this.hookRegistry.executePreSignup(dto, 'password', undefined, true);
|
|
444
463
|
// Create user with override flags
|
|
445
464
|
this.logger?.debug?.(`Creating admin user record for: ${dto.email} || ${dto.username} || ${dto.phone} (isEmailVerified: ${dto.isEmailVerified || false}, isPhoneVerified: ${dto.isPhoneVerified || false})`);
|
|
446
465
|
const user = this.userRepository.create({
|
|
@@ -521,6 +540,14 @@ class AuthService {
|
|
|
521
540
|
this.logger?.error?.(`Admin signup failed - database error: ${errorMessage}`);
|
|
522
541
|
throw error;
|
|
523
542
|
}
|
|
543
|
+
// ============================================================================
|
|
544
|
+
// Lifecycle Hook: afterSignup
|
|
545
|
+
// ============================================================================
|
|
546
|
+
// Execute afterSignup hook immediately after account creation (non-blocking)
|
|
547
|
+
await this.hookRegistry.executeAfterSignup(savedUser, {
|
|
548
|
+
signupType: 'password',
|
|
549
|
+
adminSignup: true,
|
|
550
|
+
});
|
|
524
551
|
// No tokens, no challenge system, no verification emails - pure user creation
|
|
525
552
|
// Return sanitized user object (excludes passwordHash and other sensitive fields)
|
|
526
553
|
const userDto = user_response_dto_1.UserResponseDto.fromEntity(savedUser);
|
|
@@ -648,6 +675,21 @@ class AuthService {
|
|
|
648
675
|
// Social-only user: no password (NULL in database)
|
|
649
676
|
passwordHash = null;
|
|
650
677
|
}
|
|
678
|
+
// ============================================================================
|
|
679
|
+
// Lifecycle Hook: preSignup
|
|
680
|
+
// ============================================================================
|
|
681
|
+
// Execute preSignup hook before user creation (admin social signup)
|
|
682
|
+
// Hook can throw NAuthException with PRESIGNUP_FAILED to block signup with custom message
|
|
683
|
+
// Convert AdminSignupSocialDTO to profile-like structure for hook
|
|
684
|
+
const profileData = {
|
|
685
|
+
email: dto.email,
|
|
686
|
+
id: dto.providerId,
|
|
687
|
+
firstName: dto.firstName,
|
|
688
|
+
lastName: dto.lastName,
|
|
689
|
+
verified: true, // Admin signup always has verified email
|
|
690
|
+
raw: dto.socialMetadata,
|
|
691
|
+
};
|
|
692
|
+
await this.hookRegistry.executePreSignup(profileData, 'social', dto.provider, true);
|
|
651
693
|
// Create user with override flags
|
|
652
694
|
// Note: Email is always verified for social imports (like normal social signup)
|
|
653
695
|
this.logger?.debug?.(`Creating admin social user record for: ${dto.email} || ${dto.username} || ${dto.phone} (isEmailVerified: true [auto-verified for social], isPhoneVerified: ${dto.isPhoneVerified || false})`);
|
|
@@ -680,6 +722,15 @@ class AuthService {
|
|
|
680
722
|
savedUser.hasSocialAuth = true;
|
|
681
723
|
savedUser.socialProviders = [dto.provider];
|
|
682
724
|
// ============================================================================
|
|
725
|
+
// Lifecycle Hook: afterSignup
|
|
726
|
+
// ============================================================================
|
|
727
|
+
// Execute afterSignup hook immediately after account creation (non-blocking)
|
|
728
|
+
await this.hookRegistry.executeAfterSignup(savedUser, {
|
|
729
|
+
signupType: 'social',
|
|
730
|
+
provider: dto.provider,
|
|
731
|
+
adminSignup: true,
|
|
732
|
+
});
|
|
733
|
+
// ============================================================================
|
|
683
734
|
// Audit: Record account creation by admin (social import)
|
|
684
735
|
// ============================================================================
|
|
685
736
|
try {
|
|
@@ -1868,18 +1919,10 @@ class AuthService {
|
|
|
1868
1919
|
}
|
|
1869
1920
|
}
|
|
1870
1921
|
// ============================================================================
|
|
1871
|
-
// Lifecycle Hook: afterLogin
|
|
1922
|
+
// Lifecycle Hook: afterLogin (TODO: Implement provider-based hook)
|
|
1872
1923
|
// ============================================================================
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
await this.config.hooks.afterLogin(user, session);
|
|
1876
|
-
}
|
|
1877
|
-
catch (hookError) {
|
|
1878
|
-
const errorMessage = hookError instanceof Error ? hookError.message : 'Unknown error';
|
|
1879
|
-
// Non-blocking: auth succeeded; hook errors should not break login
|
|
1880
|
-
this.logger?.error?.(`afterLogin hook failed (continuing): ${errorMessage}`, { error: hookError });
|
|
1881
|
-
}
|
|
1882
|
-
}
|
|
1924
|
+
// TODO: Implement provider-based hook for afterLogin
|
|
1925
|
+
// await this.hookRegistry.executeAfterLogin(user, session);
|
|
1883
1926
|
// ============================================================================
|
|
1884
1927
|
// Trusted Device Token Management (Remember Device Feature)
|
|
1885
1928
|
// ============================================================================
|
|
@@ -3521,22 +3564,24 @@ class AuthService {
|
|
|
3521
3564
|
if (!user || !user.passwordHash) {
|
|
3522
3565
|
throw new nauth_exception_1.NAuthException(error_codes_enum_1.AuthErrorCode.NOT_FOUND, 'User not found');
|
|
3523
3566
|
}
|
|
3524
|
-
//
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3567
|
+
// ============================================================================
|
|
3568
|
+
// Lifecycle Hook: beforePasswordChange (TODO: Implement provider-based hook)
|
|
3569
|
+
// ============================================================================
|
|
3570
|
+
// TODO: Implement provider-based hook for beforePasswordChange
|
|
3571
|
+
// const allowed = await this.hookRegistry.executeBeforePasswordChange(dto.sub, dto.oldPassword);
|
|
3572
|
+
// if (!allowed) {
|
|
3573
|
+
// throw new NAuthException(AuthErrorCode.PASSWORD_CHANGE_NOT_ALLOWED, 'Password change not allowed');
|
|
3574
|
+
// }
|
|
3531
3575
|
// Verify old password
|
|
3532
3576
|
const isValid = await this.passwordService.verifyPassword(dto.oldPassword, user.passwordHash);
|
|
3533
3577
|
if (!isValid) {
|
|
3534
3578
|
throw new nauth_exception_1.NAuthException(error_codes_enum_1.AuthErrorCode.PASSWORD_INCORRECT, 'Current password is incorrect');
|
|
3535
3579
|
}
|
|
3536
|
-
//
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3580
|
+
// ============================================================================
|
|
3581
|
+
// Lifecycle Hook: afterPasswordChange (TODO: Implement provider-based hook)
|
|
3582
|
+
// ============================================================================
|
|
3583
|
+
// TODO: Implement provider-based hook for afterPasswordChange
|
|
3584
|
+
// await this.hookRegistry.executeAfterPasswordChange(dto.sub);
|
|
3540
3585
|
await this.updateUserPassword({
|
|
3541
3586
|
user,
|
|
3542
3587
|
newPassword: dto.newPassword,
|
|
@@ -4124,18 +4169,10 @@ class AuthService {
|
|
|
4124
4169
|
}
|
|
4125
4170
|
}
|
|
4126
4171
|
// ============================================================================
|
|
4127
|
-
// Lifecycle Hook: afterLoginFailed
|
|
4172
|
+
// Lifecycle Hook: afterLoginFailed (TODO: Implement provider-based hook)
|
|
4128
4173
|
// ============================================================================
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
await this.config.hooks.afterLoginFailed(identifier, reason || 'unknown');
|
|
4132
|
-
}
|
|
4133
|
-
catch (hookError) {
|
|
4134
|
-
const errorMessage = hookError instanceof Error ? hookError.message : 'Unknown error';
|
|
4135
|
-
// Non-blocking: login already failed; do not throw
|
|
4136
|
-
this.logger?.error?.(`afterLoginFailed hook failed (continuing): ${errorMessage}`, { error: hookError });
|
|
4137
|
-
}
|
|
4138
|
-
}
|
|
4174
|
+
// TODO: Implement provider-based hook for afterLoginFailed
|
|
4175
|
+
// await this.hookRegistry.executeAfterLoginFailed(identifier, reason || 'unknown');
|
|
4139
4176
|
}
|
|
4140
4177
|
/**
|
|
4141
4178
|
* Records a login attempt with client context.
|