@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.
Files changed (184) hide show
  1. package/LICENSE +90 -0
  2. package/README.md +9 -0
  3. package/package.json +8 -3
  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,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
- }
@@ -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
- }