@nauth-toolkit/core 0.1.0 → 0.1.5
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/LICENSE +90 -0
- package/README.md +9 -0
- package/package.json +8 -3
- package/jest.config.js +0 -15
- package/jest.setup.ts +0 -6
- package/src/adapters/database-columns.ts +0 -165
- package/src/adapters/express.adapter.ts +0 -385
- package/src/adapters/fastify.adapter.ts +0 -416
- package/src/adapters/index.ts +0 -16
- package/src/adapters/storage.factory.ts +0 -143
- package/src/bootstrap.ts +0 -374
- package/src/dto/auth-challenge.dto.ts +0 -231
- package/src/dto/auth-response.dto.ts +0 -253
- package/src/dto/challenge-response.dto.ts +0 -234
- package/src/dto/change-password-request.dto.ts +0 -50
- package/src/dto/change-password-response.dto.ts +0 -29
- package/src/dto/change-password.dto.ts +0 -57
- package/src/dto/error-response.dto.ts +0 -136
- package/src/dto/get-available-methods.dto.ts +0 -55
- package/src/dto/get-challenge-data-response.dto.ts +0 -28
- package/src/dto/get-challenge-data.dto.ts +0 -69
- package/src/dto/get-client-info.dto.ts +0 -104
- package/src/dto/get-device-token-response.dto.ts +0 -25
- package/src/dto/get-events-by-type.dto.ts +0 -76
- package/src/dto/get-ip-address-response.dto.ts +0 -24
- package/src/dto/get-mfa-status.dto.ts +0 -94
- package/src/dto/get-risk-assessment-history.dto.ts +0 -39
- package/src/dto/get-session-id-response.dto.ts +0 -25
- package/src/dto/get-setup-data-response.dto.ts +0 -31
- package/src/dto/get-setup-data.dto.ts +0 -75
- package/src/dto/get-suspicious-activity.dto.ts +0 -42
- package/src/dto/get-user-agent-response.dto.ts +0 -23
- package/src/dto/get-user-auth-history.dto.ts +0 -95
- package/src/dto/get-user-by-email.dto.ts +0 -61
- package/src/dto/get-user-by-id.dto.ts +0 -46
- package/src/dto/get-user-devices.dto.ts +0 -53
- package/src/dto/get-user-response.dto.ts +0 -17
- package/src/dto/has-provider.dto.ts +0 -56
- package/src/dto/index.ts +0 -57
- package/src/dto/is-trusted-device-response.dto.ts +0 -34
- package/src/dto/list-providers-response.dto.ts +0 -23
- package/src/dto/login.dto.ts +0 -95
- package/src/dto/logout-all-response.dto.ts +0 -24
- package/src/dto/logout-all.dto.ts +0 -65
- package/src/dto/logout-response.dto.ts +0 -25
- package/src/dto/logout.dto.ts +0 -64
- package/src/dto/refresh-token.dto.ts +0 -36
- package/src/dto/remove-devices.dto.ts +0 -85
- package/src/dto/resend-code-response.dto.ts +0 -32
- package/src/dto/resend-code.dto.ts +0 -51
- package/src/dto/reset-password.dto.ts +0 -115
- package/src/dto/respond-challenge.dto.ts +0 -272
- package/src/dto/set-mfa-exemption.dto.ts +0 -112
- package/src/dto/set-must-change-password-response.dto.ts +0 -27
- package/src/dto/set-must-change-password.dto.ts +0 -46
- package/src/dto/set-preferred-method.dto.ts +0 -80
- package/src/dto/setup-mfa.dto.ts +0 -98
- package/src/dto/signup.dto.ts +0 -174
- package/src/dto/social-auth.dto.ts +0 -422
- package/src/dto/trust-device-response.dto.ts +0 -30
- package/src/dto/trust-device.dto.ts +0 -9
- package/src/dto/update-user-attributes-request.dto.ts +0 -51
- package/src/dto/user-response.dto.ts +0 -138
- package/src/dto/user-update.dto.ts +0 -222
- package/src/dto/verify-email.dto.ts +0 -313
- package/src/dto/verify-mfa-code.dto.ts +0 -103
- package/src/dto/verify-phone-by-sub.dto.ts +0 -78
- package/src/dto/verify-phone.dto.ts +0 -245
- package/src/entities/auth-audit.entity.ts +0 -232
- package/src/entities/challenge-session.entity.ts +0 -116
- package/src/entities/index.ts +0 -29
- package/src/entities/login-attempt.entity.ts +0 -64
- package/src/entities/mfa-device.entity.ts +0 -151
- package/src/entities/rate-limit.entity.ts +0 -44
- package/src/entities/session.entity.ts +0 -180
- package/src/entities/social-account.entity.ts +0 -96
- package/src/entities/storage-lock.entity.ts +0 -39
- package/src/entities/trusted-device.entity.ts +0 -112
- package/src/entities/user.entity.ts +0 -243
- package/src/entities/verification-token.entity.ts +0 -141
- package/src/enums/auth-audit-event-type.enum.ts +0 -360
- package/src/enums/error-codes.enum.ts +0 -420
- package/src/enums/mfa-method.enum.ts +0 -97
- package/src/enums/risk-factor.enum.ts +0 -111
- package/src/exceptions/nauth.exception.ts +0 -231
- package/src/handlers/auth.handler.ts +0 -260
- package/src/handlers/client-info.handler.ts +0 -101
- package/src/handlers/csrf.handler.ts +0 -156
- package/src/handlers/token-delivery.handler.ts +0 -118
- package/src/index.ts +0 -118
- package/src/interfaces/client-info.interface.ts +0 -85
- package/src/interfaces/config.interface.ts +0 -2135
- package/src/interfaces/entities.interface.ts +0 -226
- package/src/interfaces/index.ts +0 -15
- package/src/interfaces/logger.interface.ts +0 -283
- package/src/interfaces/mfa-provider.interface.ts +0 -154
- package/src/interfaces/oauth.interface.ts +0 -148
- package/src/interfaces/provider.interface.ts +0 -47
- package/src/interfaces/social-auth-provider.interface.ts +0 -131
- package/src/interfaces/storage-adapter.interface.ts +0 -82
- package/src/interfaces/template.interface.ts +0 -510
- package/src/interfaces/token-verifier.interface.ts +0 -110
- package/src/internal.ts +0 -178
- package/src/platform/interfaces.ts +0 -299
- package/src/schemas/auth-config.schema.ts +0 -646
- package/src/services/adaptive-mfa-decision.service.spec.ts +0 -1058
- package/src/services/adaptive-mfa-decision.service.ts +0 -457
- package/src/services/auth-audit.service.spec.ts +0 -675
- package/src/services/auth-audit.service.ts +0 -558
- package/src/services/auth-challenge-helper.service.spec.ts +0 -3227
- package/src/services/auth-challenge-helper.service.ts +0 -825
- package/src/services/auth-flow-context-builder.service.ts +0 -520
- package/src/services/auth-flow-rules.ts +0 -202
- package/src/services/auth-flow-state-definitions.ts +0 -190
- package/src/services/auth-flow-state-machine.service.ts +0 -207
- package/src/services/auth-flow-state-machine.types.ts +0 -316
- package/src/services/auth.service.spec.ts +0 -4195
- package/src/services/auth.service.ts +0 -3727
- package/src/services/challenge.service.spec.ts +0 -1363
- package/src/services/challenge.service.ts +0 -696
- package/src/services/client-info.service.spec.ts +0 -572
- package/src/services/client-info.service.ts +0 -374
- package/src/services/csrf.service.ts +0 -54
- package/src/services/email-verification.service.spec.ts +0 -1229
- package/src/services/email-verification.service.ts +0 -578
- package/src/services/geo-location.service.spec.ts +0 -603
- package/src/services/geo-location.service.ts +0 -599
- package/src/services/index.ts +0 -13
- package/src/services/jwt.service.spec.ts +0 -882
- package/src/services/jwt.service.ts +0 -621
- package/src/services/mfa-base.service.spec.ts +0 -246
- package/src/services/mfa-base.service.ts +0 -611
- package/src/services/mfa.service.spec.ts +0 -693
- package/src/services/mfa.service.ts +0 -960
- package/src/services/password.service.spec.ts +0 -166
- package/src/services/password.service.ts +0 -309
- package/src/services/phone-verification.service.spec.ts +0 -1120
- package/src/services/phone-verification.service.ts +0 -751
- package/src/services/risk-detection.service.spec.ts +0 -1292
- package/src/services/risk-detection.service.ts +0 -1012
- package/src/services/risk-scoring.service.spec.ts +0 -204
- package/src/services/risk-scoring.service.ts +0 -131
- package/src/services/session.service.spec.ts +0 -1293
- package/src/services/session.service.ts +0 -803
- package/src/services/social-account.service.spec.ts +0 -725
- package/src/services/social-auth-base.service.spec.ts +0 -418
- package/src/services/social-auth-base.service.ts +0 -581
- package/src/services/social-auth.service.spec.ts +0 -238
- package/src/services/social-auth.service.ts +0 -436
- package/src/services/social-provider-registry.service.spec.ts +0 -238
- package/src/services/social-provider-registry.service.ts +0 -122
- package/src/services/trusted-device.service.spec.ts +0 -505
- package/src/services/trusted-device.service.ts +0 -339
- package/src/storage/account-lockout-storage.service.spec.ts +0 -310
- package/src/storage/account-lockout-storage.service.ts +0 -89
- package/src/storage/index.ts +0 -3
- package/src/storage/memory-storage.adapter.ts +0 -443
- package/src/storage/rate-limit-storage.service.spec.ts +0 -247
- package/src/storage/rate-limit-storage.service.ts +0 -38
- package/src/templates/html-template.engine.spec.ts +0 -161
- package/src/templates/html-template.engine.ts +0 -688
- package/src/templates/index.ts +0 -7
- package/src/utils/common-passwords.spec.ts +0 -230
- package/src/utils/common-passwords.ts +0 -170
- package/src/utils/context-storage.ts +0 -188
- package/src/utils/cookie-names.util.ts +0 -67
- package/src/utils/cookies.util.ts +0 -94
- package/src/utils/index.ts +0 -12
- package/src/utils/ip-extractor.spec.ts +0 -330
- package/src/utils/ip-extractor.ts +0 -220
- package/src/utils/nauth-logger.spec.ts +0 -388
- package/src/utils/nauth-logger.ts +0 -215
- package/src/utils/pii-redactor.spec.ts +0 -130
- package/src/utils/pii-redactor.ts +0 -288
- package/src/utils/setup/get-repositories.ts +0 -140
- package/src/utils/setup/init-services.ts +0 -422
- package/src/utils/setup/init-social.ts +0 -189
- package/src/utils/setup/init-storage.ts +0 -94
- package/src/utils/setup/register-mfa.ts +0 -165
- package/src/utils/setup/run-nauth-migrations.ts +0 -61
- package/src/utils/token-delivery-policy.ts +0 -38
- package/src/validators/template.validator.ts +0 -219
- package/tsconfig.json +0 -37
- package/tsconfig.lint.json +0 -6
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unified Challenge Response DTO with Comprehensive Validation
|
|
3
|
-
*
|
|
4
|
-
* Provides class-validator validation for challenge responses.
|
|
5
|
-
* This is the single source of truth for challenge response validation,
|
|
6
|
-
* used by both NestJS and Express adapters.
|
|
7
|
-
*
|
|
8
|
-
* Security Features:
|
|
9
|
-
* - All string inputs have max length (prevents DoS attacks)
|
|
10
|
-
* - Phone numbers validated against E.164 format
|
|
11
|
-
* - Password strength enforced (8-128 chars)
|
|
12
|
-
* - Conditional validation based on challenge type
|
|
13
|
-
* - Enum validation prevents invalid challenge types
|
|
14
|
-
*
|
|
15
|
-
* @module RespondChallengeDTO
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import { IsString, IsEnum, ValidateIf, IsObject, MinLength, MaxLength, Matches, Length, IsUUID } from 'class-validator';
|
|
19
|
-
import { Transform } from 'class-transformer';
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Challenge type enum for validation
|
|
23
|
-
*/
|
|
24
|
-
export enum ChallengeType {
|
|
25
|
-
VERIFY_EMAIL = 'VERIFY_EMAIL',
|
|
26
|
-
VERIFY_PHONE = 'VERIFY_PHONE',
|
|
27
|
-
MFA_REQUIRED = 'MFA_REQUIRED',
|
|
28
|
-
FORCE_CHANGE_PASSWORD = 'FORCE_CHANGE_PASSWORD',
|
|
29
|
-
MFA_SETUP_REQUIRED = 'MFA_SETUP_REQUIRED',
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* MFA method enum for validation
|
|
34
|
-
*/
|
|
35
|
-
export enum MFAMethodType {
|
|
36
|
-
SMS = 'sms',
|
|
37
|
-
EMAIL = 'email',
|
|
38
|
-
TOTP = 'totp',
|
|
39
|
-
PASSKEY = 'passkey',
|
|
40
|
-
BACKUP = 'backup',
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Unified DTO for responding to authentication challenges
|
|
45
|
-
*
|
|
46
|
-
* Uses conditional validation (@ValidateIf) to validate fields based on challenge type.
|
|
47
|
-
* This ensures proper validation while maintaining a single endpoint for all challenge types.
|
|
48
|
-
*
|
|
49
|
-
* Security:
|
|
50
|
-
* - All strings have max length constraints matching DB limits
|
|
51
|
-
* - Phone numbers validated against E.164 format (prevents SQL injection)
|
|
52
|
-
* - Verification codes validated for length (4-10 chars)
|
|
53
|
-
* - Passwords validated for strength requirements
|
|
54
|
-
* - Session tokens validated as UUID v4 format (prevents injection)
|
|
55
|
-
*
|
|
56
|
-
* @example
|
|
57
|
-
* ```typescript
|
|
58
|
-
* @Controller('auth')
|
|
59
|
-
* export class AuthController {
|
|
60
|
-
* @Post('respond-challenge')
|
|
61
|
-
* async respondToChallenge(@Body() dto: RespondChallengeDTO) {
|
|
62
|
-
* return await this.authService.respondToChallenge(dto);
|
|
63
|
-
* }
|
|
64
|
-
* }
|
|
65
|
-
* ```
|
|
66
|
-
*/
|
|
67
|
-
export class RespondChallengeDTO {
|
|
68
|
-
/**
|
|
69
|
-
* Challenge session token (UUID v4)
|
|
70
|
-
* Always required
|
|
71
|
-
*
|
|
72
|
-
* Validation:
|
|
73
|
-
* - Must be a valid UUID v4 format
|
|
74
|
-
* - Generated using randomUUID() in challenge service
|
|
75
|
-
* - Matches DB constraint: varchar(255) but UUID format enforced
|
|
76
|
-
*
|
|
77
|
-
* Sanitization:
|
|
78
|
-
* - Trimmed
|
|
79
|
-
* - Lowercased for consistency
|
|
80
|
-
*
|
|
81
|
-
* @example "a21b654c-2746-4168-acee-c175083a65cd"
|
|
82
|
-
*/
|
|
83
|
-
@IsUUID('4', { message: 'Session token must be a valid UUID v4 format' })
|
|
84
|
-
@Transform(({ value }) => {
|
|
85
|
-
if (typeof value === 'string') {
|
|
86
|
-
return value.trim().toLowerCase();
|
|
87
|
-
}
|
|
88
|
-
return value;
|
|
89
|
-
})
|
|
90
|
-
session!: string;
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Challenge type being responded to
|
|
94
|
-
* Always required
|
|
95
|
-
*/
|
|
96
|
-
@IsEnum(ChallengeType, {
|
|
97
|
-
message:
|
|
98
|
-
'Challenge type must be one of: VERIFY_EMAIL, VERIFY_PHONE, MFA_REQUIRED, FORCE_CHANGE_PASSWORD, MFA_SETUP_REQUIRED',
|
|
99
|
-
})
|
|
100
|
-
type!: ChallengeType;
|
|
101
|
-
|
|
102
|
-
// ============================================================================
|
|
103
|
-
// VERIFY_EMAIL / VERIFY_PHONE / MFA_REQUIRED (code-based)
|
|
104
|
-
// ============================================================================
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Verification code
|
|
108
|
-
* Required for:
|
|
109
|
-
* - VERIFY_EMAIL
|
|
110
|
-
* - VERIFY_PHONE (when verifying code)
|
|
111
|
-
* - MFA_REQUIRED (for SMS/Email/TOTP/Backup methods)
|
|
112
|
-
*
|
|
113
|
-
* Validation:
|
|
114
|
-
* - Must be a string
|
|
115
|
-
* - Length 4-10 characters (covers all code types)
|
|
116
|
-
* - Alphanumeric only
|
|
117
|
-
*
|
|
118
|
-
* Note: NOT trimmed (codes should be exact)
|
|
119
|
-
*/
|
|
120
|
-
@ValidateIf(
|
|
121
|
-
(o) =>
|
|
122
|
-
o.type === ChallengeType.VERIFY_EMAIL ||
|
|
123
|
-
(o.type === ChallengeType.VERIFY_PHONE && !o.phone) ||
|
|
124
|
-
(o.type === ChallengeType.MFA_REQUIRED && o.method !== MFAMethodType.PASSKEY),
|
|
125
|
-
)
|
|
126
|
-
@IsString({ message: 'Code must be a string' })
|
|
127
|
-
@Length(4, 10, { message: 'Code must be between 4 and 10 characters' })
|
|
128
|
-
@Matches(/^[A-Za-z0-9]+$/, { message: 'Code can only contain letters and numbers' })
|
|
129
|
-
code?: string;
|
|
130
|
-
|
|
131
|
-
// ============================================================================
|
|
132
|
-
// VERIFY_PHONE (phone collection)
|
|
133
|
-
// ============================================================================
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Phone number in E.164 format
|
|
137
|
-
* Required for VERIFY_PHONE when collecting phone number (first step)
|
|
138
|
-
*
|
|
139
|
-
* Validation:
|
|
140
|
-
* - Must be a string
|
|
141
|
-
* - Must match E.164 format: +[country code][number]
|
|
142
|
-
* - Example: +14155552671
|
|
143
|
-
* - Max 20 characters (matches DB limit)
|
|
144
|
-
*
|
|
145
|
-
* Sanitization:
|
|
146
|
-
* - Trimmed
|
|
147
|
-
* - Only digits and leading + allowed
|
|
148
|
-
*/
|
|
149
|
-
@ValidateIf((o) => o.type === ChallengeType.VERIFY_PHONE && !o.code)
|
|
150
|
-
@IsString({ message: 'Phone must be a string' })
|
|
151
|
-
@MaxLength(20, { message: 'Phone number must not exceed 20 characters' })
|
|
152
|
-
@Matches(/^\+[1-9]\d{1,14}$/, {
|
|
153
|
-
message: 'Phone must be in E.164 format (e.g., +14155552671)',
|
|
154
|
-
})
|
|
155
|
-
@Transform(({ value }) => {
|
|
156
|
-
if (typeof value === 'string') {
|
|
157
|
-
return value.trim();
|
|
158
|
-
}
|
|
159
|
-
return value;
|
|
160
|
-
})
|
|
161
|
-
phone?: string;
|
|
162
|
-
|
|
163
|
-
// ============================================================================
|
|
164
|
-
// FORCE_CHANGE_PASSWORD
|
|
165
|
-
// ============================================================================
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* New password
|
|
169
|
-
* Required for FORCE_CHANGE_PASSWORD challenge
|
|
170
|
-
*
|
|
171
|
-
* Validation:
|
|
172
|
-
* - Must be a string
|
|
173
|
-
* - Min 8 characters (security requirement)
|
|
174
|
-
* - Max 128 characters (prevents DoS via bcrypt)
|
|
175
|
-
*
|
|
176
|
-
* Note: NOT trimmed (passwords can have leading/trailing spaces)
|
|
177
|
-
*/
|
|
178
|
-
@ValidateIf((o) => o.type === ChallengeType.FORCE_CHANGE_PASSWORD)
|
|
179
|
-
@IsString({ message: 'New password must be a string' })
|
|
180
|
-
@MinLength(8, { message: 'Password must be at least 8 characters' })
|
|
181
|
-
@MaxLength(128, { message: 'Password must not exceed 128 characters' })
|
|
182
|
-
newPassword?: string;
|
|
183
|
-
|
|
184
|
-
// ============================================================================
|
|
185
|
-
// MFA_REQUIRED / MFA_SETUP_REQUIRED
|
|
186
|
-
// ============================================================================
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* MFA method being used or set up
|
|
190
|
-
* Required for:
|
|
191
|
-
* - MFA_REQUIRED challenge (method being used for verification)
|
|
192
|
-
* - MFA_SETUP_REQUIRED challenge (method being set up)
|
|
193
|
-
*
|
|
194
|
-
* Validation:
|
|
195
|
-
* - Must be one of: sms, email, totp, passkey, backup
|
|
196
|
-
*/
|
|
197
|
-
@ValidateIf((o) => o.type === ChallengeType.MFA_REQUIRED || o.type === ChallengeType.MFA_SETUP_REQUIRED)
|
|
198
|
-
@IsEnum(MFAMethodType, { message: 'MFA method must be one of: sms, email, totp, passkey, backup' })
|
|
199
|
-
method?: MFAMethodType;
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Passkey credential
|
|
203
|
-
* Required for MFA_REQUIRED when method is 'passkey'
|
|
204
|
-
*
|
|
205
|
-
* Validation:
|
|
206
|
-
* - Must be an object
|
|
207
|
-
* - Contains WebAuthn credential from navigator.credentials.get()
|
|
208
|
-
*/
|
|
209
|
-
@ValidateIf((o) => o.type === ChallengeType.MFA_REQUIRED && o.method === MFAMethodType.PASSKEY)
|
|
210
|
-
@IsObject({ message: 'Credential must be an object' })
|
|
211
|
-
credential?: Record<string, unknown>;
|
|
212
|
-
|
|
213
|
-
// ============================================================================
|
|
214
|
-
// MFA_SETUP_REQUIRED
|
|
215
|
-
// ============================================================================
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* MFA setup data (method-specific)
|
|
219
|
-
* Required for MFA_SETUP_REQUIRED challenge
|
|
220
|
-
*
|
|
221
|
-
* Expected structure by method:
|
|
222
|
-
* - SMS: { phone: string, code: string }
|
|
223
|
-
* - Email: { code: string }
|
|
224
|
-
* - TOTP: { code: string }
|
|
225
|
-
* - Passkey: { credential: Record<string, unknown> }
|
|
226
|
-
*
|
|
227
|
-
* Validation:
|
|
228
|
-
* - Must be an object
|
|
229
|
-
* - Structure validated by MFA provider services
|
|
230
|
-
*/
|
|
231
|
-
@ValidateIf((o) => o.type === ChallengeType.MFA_SETUP_REQUIRED)
|
|
232
|
-
@IsObject({ message: 'Setup data must be an object' })
|
|
233
|
-
setupData?: Record<string, unknown>;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Helper type guards for challenge response
|
|
238
|
-
*
|
|
239
|
-
* Use these to narrow TypeScript types in your application logic.
|
|
240
|
-
*
|
|
241
|
-
* @example
|
|
242
|
-
* ```typescript
|
|
243
|
-
* if (RespondChallengeValidation.isEmailVerification(dto)) {
|
|
244
|
-
* // TypeScript knows dto.code is available
|
|
245
|
-
* }
|
|
246
|
-
* ```
|
|
247
|
-
*/
|
|
248
|
-
export namespace RespondChallengeValidation {
|
|
249
|
-
export function isEmailVerification(dto: RespondChallengeDTO): boolean {
|
|
250
|
-
return dto.type === ChallengeType.VERIFY_EMAIL && !!dto.code;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
export function isPhoneCollection(dto: RespondChallengeDTO): boolean {
|
|
254
|
-
return dto.type === ChallengeType.VERIFY_PHONE && !!dto.phone;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
export function isPhoneVerification(dto: RespondChallengeDTO): boolean {
|
|
258
|
-
return dto.type === ChallengeType.VERIFY_PHONE && !!dto.code;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
export function isPasswordChange(dto: RespondChallengeDTO): boolean {
|
|
262
|
-
return dto.type === ChallengeType.FORCE_CHANGE_PASSWORD && !!dto.newPassword;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
export function isMFAVerification(dto: RespondChallengeDTO): boolean {
|
|
266
|
-
return dto.type === ChallengeType.MFA_REQUIRED && !!dto.method;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
export function isMFASetup(dto: RespondChallengeDTO): boolean {
|
|
270
|
-
return dto.type === ChallengeType.MFA_SETUP_REQUIRED && !!dto.method && !!dto.setupData;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DTO for setting MFA exemption
|
|
3
|
-
*
|
|
4
|
-
* Used to grant or revoke a user's exemption from multi-factor authentication requirements.
|
|
5
|
-
* Admin-only operation.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```typescript
|
|
9
|
-
* const result = await mfaService.setMFAExemption({
|
|
10
|
-
* userSub: 'user-uuid',
|
|
11
|
-
* exempt: true,
|
|
12
|
-
* reason: 'Business partner requires MFA bypass',
|
|
13
|
-
* grantedBy: 'admin@example.com'
|
|
14
|
-
* });
|
|
15
|
-
* ```
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import { IsUUID, IsBoolean, IsOptional, IsString, MaxLength } from 'class-validator';
|
|
19
|
-
import { Transform } from 'class-transformer';
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* DTO for setting MFA exemption
|
|
23
|
-
*/
|
|
24
|
-
export class SetMFAExemptionDTO {
|
|
25
|
-
/**
|
|
26
|
-
* User's unique identifier (UUID v4)
|
|
27
|
-
*
|
|
28
|
-
* Validation:
|
|
29
|
-
* - Must be a valid UUID v4 format
|
|
30
|
-
* - Matches DB constraint: char(36) or uuid
|
|
31
|
-
*
|
|
32
|
-
* Sanitization:
|
|
33
|
-
* - Trimmed
|
|
34
|
-
* - Lowercased for consistency
|
|
35
|
-
*
|
|
36
|
-
* @example "a21b654c-2746-4168-acee-c175083a65cd"
|
|
37
|
-
*/
|
|
38
|
-
@IsUUID('4', { message: 'User sub must be a valid UUID v4 format' })
|
|
39
|
-
@Transform(({ value }) => {
|
|
40
|
-
if (typeof value === 'string') {
|
|
41
|
-
return value.trim().toLowerCase();
|
|
42
|
-
}
|
|
43
|
-
return value;
|
|
44
|
-
})
|
|
45
|
-
userSub!: string;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Whether to grant exemption (true) or revoke exemption (false)
|
|
49
|
-
*/
|
|
50
|
-
@IsBoolean({ message: 'Exempt must be a boolean' })
|
|
51
|
-
exempt!: boolean;
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Optional reason for the exemption status change
|
|
55
|
-
*
|
|
56
|
-
* Validation:
|
|
57
|
-
* - Max 500 characters
|
|
58
|
-
*
|
|
59
|
-
* Sanitization:
|
|
60
|
-
* - Trimmed
|
|
61
|
-
*/
|
|
62
|
-
@IsOptional()
|
|
63
|
-
@IsString({ message: 'Reason must be a string' })
|
|
64
|
-
@MaxLength(500, { message: 'Reason must not exceed 500 characters' })
|
|
65
|
-
@Transform(({ value }) => {
|
|
66
|
-
if (typeof value === 'string') {
|
|
67
|
-
return value.trim();
|
|
68
|
-
}
|
|
69
|
-
return value;
|
|
70
|
-
})
|
|
71
|
-
reason?: string | null;
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Optional identifier of the admin performing this action
|
|
75
|
-
*
|
|
76
|
-
* Validation:
|
|
77
|
-
* - Max 255 characters
|
|
78
|
-
*
|
|
79
|
-
* Sanitization:
|
|
80
|
-
* - Trimmed
|
|
81
|
-
*/
|
|
82
|
-
@IsOptional()
|
|
83
|
-
@IsString({ message: 'Granted by must be a string' })
|
|
84
|
-
@MaxLength(255, { message: 'Granted by must not exceed 255 characters' })
|
|
85
|
-
@Transform(({ value }) => {
|
|
86
|
-
if (typeof value === 'string') {
|
|
87
|
-
return value.trim();
|
|
88
|
-
}
|
|
89
|
-
return value;
|
|
90
|
-
})
|
|
91
|
-
grantedBy?: string | null;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Response DTO for setting MFA exemption
|
|
96
|
-
*/
|
|
97
|
-
export class SetMFAExemptionResponseDTO {
|
|
98
|
-
/**
|
|
99
|
-
* Whether user is exempt from MFA requirements
|
|
100
|
-
*/
|
|
101
|
-
mfaExempt!: boolean;
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Reason for MFA exemption (if exempt)
|
|
105
|
-
*/
|
|
106
|
-
mfaExemptReason!: string | null;
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Date when MFA exemption was granted (if exempt)
|
|
110
|
-
*/
|
|
111
|
-
mfaExemptGrantedAt!: Date | null;
|
|
112
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Set Must Change Password Response DTO
|
|
3
|
-
*
|
|
4
|
-
* Response DTO for setting must change password flag.
|
|
5
|
-
* No validators needed - this is generated internally by the library.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```typescript
|
|
9
|
-
* await authService.setMustChangePassword({
|
|
10
|
-
* userId: 'user-uuid'
|
|
11
|
-
* });
|
|
12
|
-
* // Returns: { success: true }
|
|
13
|
-
* ```
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Response DTO for set must change password
|
|
18
|
-
*/
|
|
19
|
-
export class SetMustChangePasswordResponseDTO {
|
|
20
|
-
/**
|
|
21
|
-
* Success indicator
|
|
22
|
-
* Always true on successful flag set
|
|
23
|
-
*
|
|
24
|
-
* @example true
|
|
25
|
-
*/
|
|
26
|
-
success!: boolean;
|
|
27
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Set Must Change Password DTO
|
|
3
|
-
*
|
|
4
|
-
* Request DTO for requiring a user to change their password on next login.
|
|
5
|
-
*
|
|
6
|
-
* Security:
|
|
7
|
-
* - User ID validated (UUID)
|
|
8
|
-
* - Prevents unauthorized password change requirements
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```typescript
|
|
12
|
-
* await authService.setMustChangePassword({
|
|
13
|
-
* userId: 'user-uuid'
|
|
14
|
-
* });
|
|
15
|
-
* ```
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import { IsUUID } from 'class-validator';
|
|
19
|
-
import { Transform } from 'class-transformer';
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Request DTO for setting must change password flag
|
|
23
|
-
*/
|
|
24
|
-
export class SetMustChangePasswordDTO {
|
|
25
|
-
/**
|
|
26
|
-
* User's unique identifier (UUID v4)
|
|
27
|
-
*
|
|
28
|
-
* Validation:
|
|
29
|
-
* - Must be a valid UUID v4 format
|
|
30
|
-
* - Matches DB constraint: char(36) or uuid
|
|
31
|
-
*
|
|
32
|
-
* Sanitization:
|
|
33
|
-
* - Trimmed
|
|
34
|
-
* - Lowercased for consistency
|
|
35
|
-
*
|
|
36
|
-
* @example "a21b654c-2746-4168-acee-c175083a65cd"
|
|
37
|
-
*/
|
|
38
|
-
@IsUUID('4', { message: 'User ID must be a valid UUID v4 format' })
|
|
39
|
-
@Transform(({ value }) => {
|
|
40
|
-
if (typeof value === 'string') {
|
|
41
|
-
return value.trim().toLowerCase();
|
|
42
|
-
}
|
|
43
|
-
return value;
|
|
44
|
-
})
|
|
45
|
-
userId!: string;
|
|
46
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DTO for setting preferred MFA method
|
|
3
|
-
*
|
|
4
|
-
* Used to set the preferred MFA method for a user.
|
|
5
|
-
* Updates the user's preferred method and device primary flags.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```typescript
|
|
9
|
-
* await mfaService.setPreferredMethod({
|
|
10
|
-
* userSub: 'user-uuid',
|
|
11
|
-
* methodType: 'totp'
|
|
12
|
-
* });
|
|
13
|
-
* ```
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { IsEnum, IsString, IsUUID, MaxLength } from 'class-validator';
|
|
17
|
-
import { Transform } from 'class-transformer';
|
|
18
|
-
import { MFAMethod } from '../enums/mfa-method.enum';
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* DTO for setting preferred MFA method
|
|
22
|
-
*/
|
|
23
|
-
export class SetPreferredMethodDTO {
|
|
24
|
-
/**
|
|
25
|
-
* User's unique identifier (UUID v4)
|
|
26
|
-
*
|
|
27
|
-
* Validation:
|
|
28
|
-
* - Must be a valid UUID v4 format
|
|
29
|
-
* - Matches DB constraint: char(36) or uuid
|
|
30
|
-
*
|
|
31
|
-
* Sanitization:
|
|
32
|
-
* - Trimmed
|
|
33
|
-
* - Lowercased for consistency
|
|
34
|
-
*
|
|
35
|
-
* @example "a21b654c-2746-4168-acee-c175083a65cd"
|
|
36
|
-
*/
|
|
37
|
-
@IsUUID('4', { message: 'User sub must be a valid UUID v4 format' })
|
|
38
|
-
@Transform(({ value }) => {
|
|
39
|
-
if (typeof value === 'string') {
|
|
40
|
-
return value.trim().toLowerCase();
|
|
41
|
-
}
|
|
42
|
-
return value;
|
|
43
|
-
})
|
|
44
|
-
userSub!: string;
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* MFA method type to set as preferred
|
|
48
|
-
*
|
|
49
|
-
* Validation:
|
|
50
|
-
* - Must be one of: totp, sms, email, passkey
|
|
51
|
-
* - Max 50 characters
|
|
52
|
-
*
|
|
53
|
-
* Sanitization:
|
|
54
|
-
* - Trimmed and lowercased
|
|
55
|
-
*
|
|
56
|
-
* @example "totp"
|
|
57
|
-
*/
|
|
58
|
-
@IsString({ message: 'Method type must be a string' })
|
|
59
|
-
@IsEnum([MFAMethod.TOTP, MFAMethod.SMS, MFAMethod.EMAIL, MFAMethod.PASSKEY], {
|
|
60
|
-
message: 'Method type must be one of: totp, sms, email, passkey',
|
|
61
|
-
})
|
|
62
|
-
@MaxLength(50, { message: 'Method type must not exceed 50 characters' })
|
|
63
|
-
@Transform(({ value }) => {
|
|
64
|
-
if (typeof value === 'string') {
|
|
65
|
-
return value.trim().toLowerCase();
|
|
66
|
-
}
|
|
67
|
-
return value;
|
|
68
|
-
})
|
|
69
|
-
methodType!: string;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Response DTO for setting preferred method
|
|
74
|
-
*/
|
|
75
|
-
export class SetPreferredMethodResponseDTO {
|
|
76
|
-
/**
|
|
77
|
-
* Success message
|
|
78
|
-
*/
|
|
79
|
-
message!: string;
|
|
80
|
-
}
|
package/src/dto/setup-mfa.dto.ts
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DTO for setting up MFA device
|
|
3
|
-
*
|
|
4
|
-
* Used to initiate MFA device setup using the appropriate provider.
|
|
5
|
-
*
|
|
6
|
-
* @example
|
|
7
|
-
* ```typescript
|
|
8
|
-
* const setup = await mfaService.setup({
|
|
9
|
-
* sub: 'user-uuid',
|
|
10
|
-
* methodName: 'totp',
|
|
11
|
-
* setupData: {}
|
|
12
|
-
* });
|
|
13
|
-
* ```
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { IsEnum, IsString, IsUUID, IsOptional, IsObject, MaxLength } from 'class-validator';
|
|
17
|
-
import { Transform } from 'class-transformer';
|
|
18
|
-
import { MFAMethod } from '../enums/mfa-method.enum';
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* DTO for setting up MFA device
|
|
22
|
-
*/
|
|
23
|
-
export class SetupMFADTO {
|
|
24
|
-
/**
|
|
25
|
-
* User's unique identifier (UUID v4)
|
|
26
|
-
*
|
|
27
|
-
* Validation:
|
|
28
|
-
* - Must be a valid UUID v4 format
|
|
29
|
-
* - Matches DB constraint: char(36) or uuid
|
|
30
|
-
*
|
|
31
|
-
* Sanitization:
|
|
32
|
-
* - Trimmed
|
|
33
|
-
* - Lowercased for consistency
|
|
34
|
-
*
|
|
35
|
-
* @example "a21b654c-2746-4168-acee-c175083a65cd"
|
|
36
|
-
*/
|
|
37
|
-
@IsUUID('4', { message: 'User sub must be a valid UUID v4 format' })
|
|
38
|
-
@Transform(({ value }) => {
|
|
39
|
-
if (typeof value === 'string') {
|
|
40
|
-
return value.trim().toLowerCase();
|
|
41
|
-
}
|
|
42
|
-
return value;
|
|
43
|
-
})
|
|
44
|
-
sub!: string;
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* MFA method name
|
|
48
|
-
*
|
|
49
|
-
* Validation:
|
|
50
|
-
* - Must be one of: totp, sms, email, passkey
|
|
51
|
-
* - Max 50 characters
|
|
52
|
-
*
|
|
53
|
-
* Sanitization:
|
|
54
|
-
* - Trimmed and lowercased
|
|
55
|
-
*
|
|
56
|
-
* @example "totp"
|
|
57
|
-
*/
|
|
58
|
-
@IsString({ message: 'Method name must be a string' })
|
|
59
|
-
@IsEnum([MFAMethod.TOTP, MFAMethod.SMS, MFAMethod.EMAIL, MFAMethod.PASSKEY], {
|
|
60
|
-
message: 'Method name must be one of: totp, sms, email, passkey',
|
|
61
|
-
})
|
|
62
|
-
@MaxLength(50, { message: 'Method name must not exceed 50 characters' })
|
|
63
|
-
@Transform(({ value }) => {
|
|
64
|
-
if (typeof value === 'string') {
|
|
65
|
-
return value.trim().toLowerCase();
|
|
66
|
-
}
|
|
67
|
-
return value;
|
|
68
|
-
})
|
|
69
|
-
methodName!: string;
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Optional provider-specific setup data
|
|
73
|
-
*
|
|
74
|
-
* Validation:
|
|
75
|
-
* - Must be an object if provided
|
|
76
|
-
* - Structure validated by MFA provider services
|
|
77
|
-
*
|
|
78
|
-
* @example { phoneNumber: '+1234567890' } for SMS
|
|
79
|
-
*/
|
|
80
|
-
@IsOptional()
|
|
81
|
-
@IsObject({ message: 'Setup data must be an object' })
|
|
82
|
-
setupData?: Record<string, unknown>;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Response DTO for MFA setup
|
|
87
|
-
*/
|
|
88
|
-
export class SetupMFAResponseDTO {
|
|
89
|
-
/**
|
|
90
|
-
* Provider-specific setup response
|
|
91
|
-
*
|
|
92
|
-
* Structure varies by method:
|
|
93
|
-
* - TOTP: { secret, qrCode, manualEntryKey }
|
|
94
|
-
* - SMS: { maskedPhone }
|
|
95
|
-
* - Passkey: WebAuthn registration options
|
|
96
|
-
*/
|
|
97
|
-
setupData!: Record<string, unknown>;
|
|
98
|
-
}
|