@nauth-toolkit/core 0.1.0 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/LICENSE +90 -0
  2. package/README.md +30 -0
  3. package/package.json +7 -2
  4. package/jest.config.js +0 -15
  5. package/jest.setup.ts +0 -6
  6. package/src/adapters/database-columns.ts +0 -165
  7. package/src/adapters/express.adapter.ts +0 -385
  8. package/src/adapters/fastify.adapter.ts +0 -416
  9. package/src/adapters/index.ts +0 -16
  10. package/src/adapters/storage.factory.ts +0 -143
  11. package/src/bootstrap.ts +0 -374
  12. package/src/dto/auth-challenge.dto.ts +0 -231
  13. package/src/dto/auth-response.dto.ts +0 -253
  14. package/src/dto/challenge-response.dto.ts +0 -234
  15. package/src/dto/change-password-request.dto.ts +0 -50
  16. package/src/dto/change-password-response.dto.ts +0 -29
  17. package/src/dto/change-password.dto.ts +0 -57
  18. package/src/dto/error-response.dto.ts +0 -136
  19. package/src/dto/get-available-methods.dto.ts +0 -55
  20. package/src/dto/get-challenge-data-response.dto.ts +0 -28
  21. package/src/dto/get-challenge-data.dto.ts +0 -69
  22. package/src/dto/get-client-info.dto.ts +0 -104
  23. package/src/dto/get-device-token-response.dto.ts +0 -25
  24. package/src/dto/get-events-by-type.dto.ts +0 -76
  25. package/src/dto/get-ip-address-response.dto.ts +0 -24
  26. package/src/dto/get-mfa-status.dto.ts +0 -94
  27. package/src/dto/get-risk-assessment-history.dto.ts +0 -39
  28. package/src/dto/get-session-id-response.dto.ts +0 -25
  29. package/src/dto/get-setup-data-response.dto.ts +0 -31
  30. package/src/dto/get-setup-data.dto.ts +0 -75
  31. package/src/dto/get-suspicious-activity.dto.ts +0 -42
  32. package/src/dto/get-user-agent-response.dto.ts +0 -23
  33. package/src/dto/get-user-auth-history.dto.ts +0 -95
  34. package/src/dto/get-user-by-email.dto.ts +0 -61
  35. package/src/dto/get-user-by-id.dto.ts +0 -46
  36. package/src/dto/get-user-devices.dto.ts +0 -53
  37. package/src/dto/get-user-response.dto.ts +0 -17
  38. package/src/dto/has-provider.dto.ts +0 -56
  39. package/src/dto/index.ts +0 -57
  40. package/src/dto/is-trusted-device-response.dto.ts +0 -34
  41. package/src/dto/list-providers-response.dto.ts +0 -23
  42. package/src/dto/login.dto.ts +0 -95
  43. package/src/dto/logout-all-response.dto.ts +0 -24
  44. package/src/dto/logout-all.dto.ts +0 -65
  45. package/src/dto/logout-response.dto.ts +0 -25
  46. package/src/dto/logout.dto.ts +0 -64
  47. package/src/dto/refresh-token.dto.ts +0 -36
  48. package/src/dto/remove-devices.dto.ts +0 -85
  49. package/src/dto/resend-code-response.dto.ts +0 -32
  50. package/src/dto/resend-code.dto.ts +0 -51
  51. package/src/dto/reset-password.dto.ts +0 -115
  52. package/src/dto/respond-challenge.dto.ts +0 -272
  53. package/src/dto/set-mfa-exemption.dto.ts +0 -112
  54. package/src/dto/set-must-change-password-response.dto.ts +0 -27
  55. package/src/dto/set-must-change-password.dto.ts +0 -46
  56. package/src/dto/set-preferred-method.dto.ts +0 -80
  57. package/src/dto/setup-mfa.dto.ts +0 -98
  58. package/src/dto/signup.dto.ts +0 -174
  59. package/src/dto/social-auth.dto.ts +0 -422
  60. package/src/dto/trust-device-response.dto.ts +0 -30
  61. package/src/dto/trust-device.dto.ts +0 -9
  62. package/src/dto/update-user-attributes-request.dto.ts +0 -51
  63. package/src/dto/user-response.dto.ts +0 -138
  64. package/src/dto/user-update.dto.ts +0 -222
  65. package/src/dto/verify-email.dto.ts +0 -313
  66. package/src/dto/verify-mfa-code.dto.ts +0 -103
  67. package/src/dto/verify-phone-by-sub.dto.ts +0 -78
  68. package/src/dto/verify-phone.dto.ts +0 -245
  69. package/src/entities/auth-audit.entity.ts +0 -232
  70. package/src/entities/challenge-session.entity.ts +0 -116
  71. package/src/entities/index.ts +0 -29
  72. package/src/entities/login-attempt.entity.ts +0 -64
  73. package/src/entities/mfa-device.entity.ts +0 -151
  74. package/src/entities/rate-limit.entity.ts +0 -44
  75. package/src/entities/session.entity.ts +0 -180
  76. package/src/entities/social-account.entity.ts +0 -96
  77. package/src/entities/storage-lock.entity.ts +0 -39
  78. package/src/entities/trusted-device.entity.ts +0 -112
  79. package/src/entities/user.entity.ts +0 -243
  80. package/src/entities/verification-token.entity.ts +0 -141
  81. package/src/enums/auth-audit-event-type.enum.ts +0 -360
  82. package/src/enums/error-codes.enum.ts +0 -420
  83. package/src/enums/mfa-method.enum.ts +0 -97
  84. package/src/enums/risk-factor.enum.ts +0 -111
  85. package/src/exceptions/nauth.exception.ts +0 -231
  86. package/src/handlers/auth.handler.ts +0 -260
  87. package/src/handlers/client-info.handler.ts +0 -101
  88. package/src/handlers/csrf.handler.ts +0 -156
  89. package/src/handlers/token-delivery.handler.ts +0 -118
  90. package/src/index.ts +0 -118
  91. package/src/interfaces/client-info.interface.ts +0 -85
  92. package/src/interfaces/config.interface.ts +0 -2135
  93. package/src/interfaces/entities.interface.ts +0 -226
  94. package/src/interfaces/index.ts +0 -15
  95. package/src/interfaces/logger.interface.ts +0 -283
  96. package/src/interfaces/mfa-provider.interface.ts +0 -154
  97. package/src/interfaces/oauth.interface.ts +0 -148
  98. package/src/interfaces/provider.interface.ts +0 -47
  99. package/src/interfaces/social-auth-provider.interface.ts +0 -131
  100. package/src/interfaces/storage-adapter.interface.ts +0 -82
  101. package/src/interfaces/template.interface.ts +0 -510
  102. package/src/interfaces/token-verifier.interface.ts +0 -110
  103. package/src/internal.ts +0 -178
  104. package/src/platform/interfaces.ts +0 -299
  105. package/src/schemas/auth-config.schema.ts +0 -646
  106. package/src/services/adaptive-mfa-decision.service.spec.ts +0 -1058
  107. package/src/services/adaptive-mfa-decision.service.ts +0 -457
  108. package/src/services/auth-audit.service.spec.ts +0 -675
  109. package/src/services/auth-audit.service.ts +0 -558
  110. package/src/services/auth-challenge-helper.service.spec.ts +0 -3227
  111. package/src/services/auth-challenge-helper.service.ts +0 -825
  112. package/src/services/auth-flow-context-builder.service.ts +0 -520
  113. package/src/services/auth-flow-rules.ts +0 -202
  114. package/src/services/auth-flow-state-definitions.ts +0 -190
  115. package/src/services/auth-flow-state-machine.service.ts +0 -207
  116. package/src/services/auth-flow-state-machine.types.ts +0 -316
  117. package/src/services/auth.service.spec.ts +0 -4195
  118. package/src/services/auth.service.ts +0 -3727
  119. package/src/services/challenge.service.spec.ts +0 -1363
  120. package/src/services/challenge.service.ts +0 -696
  121. package/src/services/client-info.service.spec.ts +0 -572
  122. package/src/services/client-info.service.ts +0 -374
  123. package/src/services/csrf.service.ts +0 -54
  124. package/src/services/email-verification.service.spec.ts +0 -1229
  125. package/src/services/email-verification.service.ts +0 -578
  126. package/src/services/geo-location.service.spec.ts +0 -603
  127. package/src/services/geo-location.service.ts +0 -599
  128. package/src/services/index.ts +0 -13
  129. package/src/services/jwt.service.spec.ts +0 -882
  130. package/src/services/jwt.service.ts +0 -621
  131. package/src/services/mfa-base.service.spec.ts +0 -246
  132. package/src/services/mfa-base.service.ts +0 -611
  133. package/src/services/mfa.service.spec.ts +0 -693
  134. package/src/services/mfa.service.ts +0 -960
  135. package/src/services/password.service.spec.ts +0 -166
  136. package/src/services/password.service.ts +0 -309
  137. package/src/services/phone-verification.service.spec.ts +0 -1120
  138. package/src/services/phone-verification.service.ts +0 -751
  139. package/src/services/risk-detection.service.spec.ts +0 -1292
  140. package/src/services/risk-detection.service.ts +0 -1012
  141. package/src/services/risk-scoring.service.spec.ts +0 -204
  142. package/src/services/risk-scoring.service.ts +0 -131
  143. package/src/services/session.service.spec.ts +0 -1293
  144. package/src/services/session.service.ts +0 -803
  145. package/src/services/social-account.service.spec.ts +0 -725
  146. package/src/services/social-auth-base.service.spec.ts +0 -418
  147. package/src/services/social-auth-base.service.ts +0 -581
  148. package/src/services/social-auth.service.spec.ts +0 -238
  149. package/src/services/social-auth.service.ts +0 -436
  150. package/src/services/social-provider-registry.service.spec.ts +0 -238
  151. package/src/services/social-provider-registry.service.ts +0 -122
  152. package/src/services/trusted-device.service.spec.ts +0 -505
  153. package/src/services/trusted-device.service.ts +0 -339
  154. package/src/storage/account-lockout-storage.service.spec.ts +0 -310
  155. package/src/storage/account-lockout-storage.service.ts +0 -89
  156. package/src/storage/index.ts +0 -3
  157. package/src/storage/memory-storage.adapter.ts +0 -443
  158. package/src/storage/rate-limit-storage.service.spec.ts +0 -247
  159. package/src/storage/rate-limit-storage.service.ts +0 -38
  160. package/src/templates/html-template.engine.spec.ts +0 -161
  161. package/src/templates/html-template.engine.ts +0 -688
  162. package/src/templates/index.ts +0 -7
  163. package/src/utils/common-passwords.spec.ts +0 -230
  164. package/src/utils/common-passwords.ts +0 -170
  165. package/src/utils/context-storage.ts +0 -188
  166. package/src/utils/cookie-names.util.ts +0 -67
  167. package/src/utils/cookies.util.ts +0 -94
  168. package/src/utils/index.ts +0 -12
  169. package/src/utils/ip-extractor.spec.ts +0 -330
  170. package/src/utils/ip-extractor.ts +0 -220
  171. package/src/utils/nauth-logger.spec.ts +0 -388
  172. package/src/utils/nauth-logger.ts +0 -215
  173. package/src/utils/pii-redactor.spec.ts +0 -130
  174. package/src/utils/pii-redactor.ts +0 -288
  175. package/src/utils/setup/get-repositories.ts +0 -140
  176. package/src/utils/setup/init-services.ts +0 -422
  177. package/src/utils/setup/init-social.ts +0 -189
  178. package/src/utils/setup/init-storage.ts +0 -94
  179. package/src/utils/setup/register-mfa.ts +0 -165
  180. package/src/utils/setup/run-nauth-migrations.ts +0 -61
  181. package/src/utils/token-delivery-policy.ts +0 -38
  182. package/src/validators/template.validator.ts +0 -219
  183. package/tsconfig.json +0 -37
  184. package/tsconfig.lint.json +0 -6
@@ -1,253 +0,0 @@
1
- import { AuthChallenge } from './auth-challenge.dto';
2
-
3
- /**
4
- * Unified Authentication Response DTO
5
- *
6
- * Used for ALL authentication operations:
7
- * - Email/password login
8
- * - User signup
9
- * - Social authentication (Google, Apple, Facebook)
10
- * - Token refresh
11
- * - Challenge completions
12
- *
13
- * This provides a consistent interface regardless of authentication method,
14
- * improving developer experience and code maintainability.
15
- *
16
- * When challenges are present, tokens will not be issued until all challenges
17
- * are completed. This ensures proper verification and security enforcement.
18
- *
19
- * No validators needed - this is generated internally by the library.
20
- *
21
- * @example
22
- * ```typescript
23
- * // Successful auth with no challenges
24
- * const loginResult = await authService.login(dto);
25
- * // { accessToken: '...', refreshToken: '...', user: {...} }
26
- *
27
- * // Auth with pending challenge
28
- * const signupResult = await authService.signup(dto);
29
- * // { challengeName: 'VERIFY_EMAIL', session: '...', challengeParameters: {...} }
30
- * ```
31
- */
32
- export class AuthResponseDTO {
33
- /**
34
- * JWT access token for API authentication
35
- * Short-lived (typically 15 minutes)
36
- *
37
- * NOTE: Only present when authentication is complete (no pending challenges)
38
- */
39
- accessToken?: string;
40
-
41
- /**
42
- * JWT refresh token for obtaining new access tokens
43
- * Long-lived (typically 30 days)
44
- *
45
- * NOTE: Only present when authentication is complete (no pending challenges)
46
- */
47
- refreshToken?: string;
48
-
49
- /**
50
- * Access token expiration timestamp
51
- * Unix timestamp in seconds
52
- *
53
- * @example 1730000000 (represents a specific date/time)
54
- *
55
- * NOTE: Only present when authentication is complete (no pending challenges)
56
- */
57
- accessTokenExpiresAt?: number;
58
-
59
- /**
60
- * Refresh token expiration timestamp
61
- * Unix timestamp in seconds
62
- *
63
- * @example 1732592000 (30 days after access token)
64
- *
65
- * NOTE: Only present when authentication is complete (no pending challenges)
66
- */
67
- refreshTokenExpiresAt?: number;
68
-
69
- /**
70
- * Whether the current device is already trusted
71
- *
72
- * When true, the device has a valid trusted device token and UI should NOT show
73
- * "trust device" popup.
74
- *
75
- * When false and rememberDevices === 'user_opt_in', UI can show popup after login
76
- * to allow user to opt-in for device trust.
77
- *
78
- * When rememberDevices === 'always', this will always be true after successful login.
79
- *
80
- * NOTE: Only present when authentication is complete (no pending challenges)
81
- */
82
- trusted?: boolean;
83
-
84
- /**
85
- * Device token for trusted device feature (UUID v4)
86
- *
87
- * Server-generated UUID token for identifying trusted devices.
88
- * Only returned when rememberDevices is not 'never' and device is trusted.
89
- *
90
- * Delivery by mode:
91
- * - **cookies mode**: Token set as `nauth_device_token` httpOnly cookie (not in response body)
92
- * - **json/hybrid mode**: Token returned in response body for mobile apps
93
- *
94
- * Mobile apps should:
95
- * - Store token in secure storage (iOS Keychain / Android EncryptedSharedPreferences)
96
- * - Send token in `X-Device-Token` header on subsequent logins
97
- * - Token persists across app restarts and survives logout
98
- *
99
- * Web apps:
100
- * - Token automatically handled via httpOnly cookie (cookies mode)
101
- * - No manual handling required
102
- *
103
- * @example "a21b654c-2746-4168-acee-c175083a65cd"
104
- *
105
- * NOTE: Only present when authentication is complete (no pending challenges)
106
- * WARNING: For JSON mode, ensure secure storage - token in response body can be intercepted
107
- */
108
- deviceToken?: string;
109
-
110
- /**
111
- * User information
112
- * Standardized across all authentication methods
113
- *
114
- * NOTE: Only present when authentication is complete (no pending challenges)
115
- */
116
- user?: {
117
- /**
118
- * User's unique identifier (UUID v4)
119
- * External identifier safe to expose in JWTs and APIs
120
- */
121
- sub: string;
122
-
123
- /**
124
- * User's email address
125
- */
126
- email: string;
127
-
128
- /**
129
- * User's first name (optional)
130
- */
131
- firstName?: string | null;
132
-
133
- /**
134
- * User's last name (optional)
135
- */
136
- lastName?: string | null;
137
-
138
- /**
139
- * User's phone number (optional)
140
- * E.164 format
141
- */
142
- phone?: string;
143
-
144
- /**
145
- * Email verification status
146
- */
147
- isEmailVerified: boolean;
148
-
149
- /**
150
- * Phone verification status
151
- */
152
- isPhoneVerified?: boolean;
153
-
154
- /**
155
- * List of linked social providers
156
- * @example ['google', 'apple']
157
- */
158
- socialProviders?: string[];
159
-
160
- /**
161
- * Whether this user has a password set
162
- * Used to determine if user can use password-based authentication
163
- * or is a pure social signup (no password, only social auth)
164
- */
165
- hasPasswordHash?: boolean;
166
- };
167
-
168
- // ============================================================================
169
- // Challenge System (Similar to AWS Cognito)
170
- // ============================================================================
171
-
172
- /**
173
- * Challenge that must be completed before authentication is granted
174
- *
175
- * When present, the user must complete this challenge using the
176
- * challenge completion endpoint before they can access the system.
177
- *
178
- * Tokens (accessToken, refreshToken) will NOT be present when a challenge exists.
179
- *
180
- * @example 'VERIFY_EMAIL' | 'VERIFY_PHONE' | 'MFA_REQUIRED'
181
- */
182
- challengeName?: AuthChallenge;
183
-
184
- /**
185
- * Temporary session identifier for challenge completion (UUID v4)
186
- *
187
- * This is NOT a JWT token - it's a temporary identifier that must be
188
- * submitted when completing the challenge. It expires after a short time
189
- * (typically 15 minutes) or after successful challenge completion.
190
- *
191
- * @example "a21b654c-2746-4168-acee-c175083a65cd"
192
- *
193
- * NOTE: Only present when challengeName is set
194
- */
195
- session?: string;
196
-
197
- /**
198
- * Challenge-specific parameters
199
- *
200
- * Contains information needed to complete the challenge, such as:
201
- * - Masked email/phone for delivery confirmation
202
- * - Challenge type details
203
- * - Instructions for the user
204
- *
205
- * NOTE: Only present when challengeName is set
206
- *
207
- * @example
208
- * ```typescript
209
- * {
210
- * email: 'user@example.com',
211
- * codeDeliveryDestination: 'u***@example.com'
212
- * }
213
- * ```
214
- */
215
- challengeParameters?: Record<string, unknown>;
216
-
217
- /**
218
- * User's unique identifier (UUID v4)
219
- * Present in both successful auth and challenge responses
220
- * Helps the client track which user is authenticating
221
- *
222
- * @example "a21b654c-2746-4168-acee-c175083a65cd"
223
- */
224
- userSub?: string;
225
- }
226
-
227
- /**
228
- * Token Response DTO
229
- *
230
- * Returned by token refresh operations
231
- * Contains new access and refresh tokens with expiration times
232
- */
233
- export interface TokenResponse {
234
- /**
235
- * New JWT access token
236
- */
237
- accessToken: string;
238
-
239
- /**
240
- * New JWT refresh token
241
- */
242
- refreshToken: string;
243
-
244
- /**
245
- * Access token expiration (Unix timestamp in seconds)
246
- */
247
- accessTokenExpiresAt: number;
248
-
249
- /**
250
- * Refresh token expiration (Unix timestamp in seconds)
251
- */
252
- refreshTokenExpiresAt: number;
253
- }
@@ -1,234 +0,0 @@
1
- /**
2
- * Challenge Response DTOs for Unified Challenge System
3
- *
4
- * Discriminated union types for responding to authentication challenges.
5
- * Each challenge type has specific required parameters.
6
- *
7
- * @module ChallengeResponseDTO
8
- */
9
-
10
- // ============================================================================
11
- // Base Types
12
- // ============================================================================
13
-
14
- /**
15
- * Base interface for all challenge responses
16
- */
17
- export interface BaseChallengeResponse {
18
- /** Challenge session token */
19
- session: string;
20
- }
21
-
22
- // ============================================================================
23
- // Email Verification Challenge
24
- // ============================================================================
25
-
26
- /**
27
- * Response for email verification challenge
28
- *
29
- * @example
30
- * ```typescript
31
- * const response: VerifyEmailResponse = {
32
- * session: 'challenge-session-token',
33
- * type: 'VERIFY_EMAIL',
34
- * code: '123456'
35
- * };
36
- * ```
37
- */
38
- export interface VerifyEmailResponse extends BaseChallengeResponse {
39
- type: 'VERIFY_EMAIL';
40
- /** 6-digit verification code sent to email */
41
- code: string;
42
- }
43
-
44
- // ============================================================================
45
- // Phone Verification Challenge
46
- // ============================================================================
47
-
48
- /**
49
- * Response for collecting phone number (first step)
50
- *
51
- * @example
52
- * ```typescript
53
- * const response: CollectPhoneResponse = {
54
- * session: 'challenge-session-token',
55
- * type: 'VERIFY_PHONE',
56
- * phone: '+1234567890'
57
- * };
58
- * ```
59
- */
60
- export interface CollectPhoneResponse extends BaseChallengeResponse {
61
- type: 'VERIFY_PHONE';
62
- /** Phone number in E.164 format */
63
- phone: string;
64
- }
65
-
66
- /**
67
- * Response for verifying phone with code (second step)
68
- *
69
- * @example
70
- * ```typescript
71
- * const response: VerifyPhoneResponse = {
72
- * session: 'challenge-session-token',
73
- * type: 'VERIFY_PHONE',
74
- * code: '123456'
75
- * };
76
- * ```
77
- */
78
- export interface VerifyPhoneResponse extends BaseChallengeResponse {
79
- type: 'VERIFY_PHONE';
80
- /** 6-digit verification code sent to phone */
81
- code: string;
82
- }
83
-
84
- // ============================================================================
85
- // MFA Verification Challenge
86
- // ============================================================================
87
-
88
- /**
89
- * Response for MFA verification with code (SMS/TOTP/Backup)
90
- *
91
- * @example
92
- * ```typescript
93
- * const response: VerifyMFACodeResponse = {
94
- * session: 'challenge-session-token',
95
- * type: 'MFA_REQUIRED',
96
- * method: 'totp',
97
- * code: '123456'
98
- * };
99
- * ```
100
- */
101
- export interface VerifyMFACodeResponse extends BaseChallengeResponse {
102
- type: 'MFA_REQUIRED';
103
- /** MFA method being used */
104
- method: 'sms' | 'totp' | 'backup';
105
- /** Verification code */
106
- code: string;
107
- }
108
-
109
- /**
110
- * Response for MFA verification with passkey
111
- *
112
- * @example
113
- * ```typescript
114
- * const response: VerifyMFAPasskeyResponse = {
115
- * session: 'challenge-session-token',
116
- * type: 'MFA_REQUIRED',
117
- * method: 'passkey',
118
- * credential: { id: '...', rawId: '...', response: {...} }
119
- * };
120
- * ```
121
- */
122
- export interface VerifyMFAPasskeyResponse extends BaseChallengeResponse {
123
- type: 'MFA_REQUIRED';
124
- /** Passkey method */
125
- method: 'passkey';
126
- /** WebAuthn credential from navigator.credentials.get() */
127
- credential: Record<string, unknown>;
128
- }
129
-
130
- // ============================================================================
131
- // Force Password Change Challenge
132
- // ============================================================================
133
-
134
- /**
135
- * Response for forced password change challenge
136
- *
137
- * @example
138
- * ```typescript
139
- * const response: ForceChangePasswordResponse = {
140
- * session: 'challenge-session-token',
141
- * type: 'FORCE_CHANGE_PASSWORD',
142
- * newPassword: 'NewSecurePassword123!'
143
- * };
144
- * ```
145
- */
146
- export interface ForceChangePasswordResponse extends BaseChallengeResponse {
147
- type: 'FORCE_CHANGE_PASSWORD';
148
- /** New password meeting security requirements */
149
- newPassword: string;
150
- }
151
-
152
- // ============================================================================
153
- // MFA Setup Challenge
154
- // ============================================================================
155
-
156
- /**
157
- * Response for MFA setup during challenge
158
- *
159
- * @example
160
- * ```typescript
161
- * // SMS setup
162
- * const smsResponse: MFASetupResponse = {
163
- * session: 'challenge-session-token',
164
- * type: 'MFA_SETUP_REQUIRED',
165
- * method: 'sms',
166
- * setupData: { phone: '+1234567890', code: '123456' }
167
- * };
168
- *
169
- * // TOTP setup
170
- * const totpResponse: MFASetupResponse = {
171
- * session: 'challenge-session-token',
172
- * type: 'MFA_SETUP_REQUIRED',
173
- * method: 'totp',
174
- * setupData: { code: '123456' }
175
- * };
176
- *
177
- * // Passkey setup
178
- * const passkeyResponse: MFASetupResponse = {
179
- * session: 'challenge-session-token',
180
- * type: 'MFA_SETUP_REQUIRED',
181
- * method: 'passkey',
182
- * setupData: { credential: {...} }
183
- * };
184
- * ```
185
- */
186
- export interface MFASetupResponse extends BaseChallengeResponse {
187
- type: 'MFA_SETUP_REQUIRED';
188
- /** MFA method being set up */
189
- method: 'sms' | 'email' | 'totp' | 'passkey';
190
- /**
191
- * Method-specific setup data
192
- * - SMS: { phone: string, code: string }
193
- * - TOTP: { code: string }
194
- * - Passkey: { credential: Record<string, unknown> }
195
- */
196
- setupData: Record<string, unknown>;
197
- }
198
-
199
- // ============================================================================
200
- // Union Type
201
- // ============================================================================
202
-
203
- /**
204
- * Discriminated union of all challenge response types
205
- *
206
- * Use this type for the unified respondToChallenge() API.
207
- * TypeScript will narrow the type based on the 'type' discriminator.
208
- *
209
- * @example
210
- * ```typescript
211
- * async function handleChallenge(response: ChallengeResponseData) {
212
- * switch (response.type) {
213
- * case 'VERIFY_EMAIL':
214
- * // TypeScript knows response.code is available
215
- * break;
216
- * case 'MFA_REQUIRED':
217
- * if (response.method === 'passkey') {
218
- * // TypeScript knows response.credential is available
219
- * } else {
220
- * // TypeScript knows response.code is available
221
- * }
222
- * break;
223
- * }
224
- * }
225
- * ```
226
- */
227
- export type ChallengeResponseData =
228
- | VerifyEmailResponse
229
- | CollectPhoneResponse
230
- | VerifyPhoneResponse
231
- | VerifyMFACodeResponse
232
- | VerifyMFAPasskeyResponse
233
- | ForceChangePasswordResponse
234
- | MFASetupResponse;
@@ -1,50 +0,0 @@
1
- /**
2
- * Change Password Request DTO
3
- *
4
- * Request DTO for changing a user's password (includes user sub).
5
- *
6
- * Security:
7
- * - User sub validated (UUID)
8
- * - Password validation enforced
9
- * - Current password required for security
10
- *
11
- * @example
12
- * ```typescript
13
- * await authService.changePassword({
14
- * sub: 'user-uuid',
15
- * currentPassword: 'OldPass123!',
16
- * newPassword: 'NewPass456!'
17
- * });
18
- * ```
19
- */
20
-
21
- import { IsUUID } from 'class-validator';
22
- import { Transform } from 'class-transformer';
23
- import { ChangePasswordDTO } from './change-password.dto';
24
-
25
- /**
26
- * Request DTO for changing password (includes user sub)
27
- */
28
- export class ChangePasswordRequestDTO extends ChangePasswordDTO {
29
- /**
30
- * User's unique identifier (UUID v4)
31
- *
32
- * Validation:
33
- * - Must be a valid UUID v4 format
34
- * - Matches DB constraint: char(36) or uuid
35
- *
36
- * Sanitization:
37
- * - Trimmed
38
- * - Lowercased for consistency
39
- *
40
- * @example "a21b654c-2746-4168-acee-c175083a65cd"
41
- */
42
- @IsUUID('4', { message: 'User sub must be a valid UUID v4 format' })
43
- @Transform(({ value }) => {
44
- if (typeof value === 'string') {
45
- return value.trim().toLowerCase();
46
- }
47
- return value;
48
- })
49
- sub!: string;
50
- }
@@ -1,29 +0,0 @@
1
- /**
2
- * Change Password Response DTO
3
- *
4
- * Response DTO for changing password.
5
- * No validators needed - this is generated internally by the library.
6
- *
7
- * @example
8
- * ```typescript
9
- * await authService.changePassword({
10
- * sub: 'user-uuid',
11
- * oldPassword: 'OldPass123!',
12
- * newPassword: 'NewPass456!'
13
- * });
14
- * // Returns: { success: true }
15
- * ```
16
- */
17
-
18
- /**
19
- * Response DTO for change password
20
- */
21
- export class ChangePasswordResponseDTO {
22
- /**
23
- * Success indicator
24
- * Always true on successful password change
25
- *
26
- * @example true
27
- */
28
- success!: boolean;
29
- }
@@ -1,57 +0,0 @@
1
- /**
2
- * Change Password DTO
3
- *
4
- * Used for authenticated password changes.
5
- * User must provide their current password for security verification.
6
- *
7
- * Security:
8
- * - Old password verified before allowing change
9
- * - New password validated for minimum strength
10
- * - Password history checked (configurable)
11
- * - Max length prevents DoS via bcrypt
12
- *
13
- * @example
14
- * ```typescript
15
- * POST /auth/change-password
16
- * Authorization: Bearer <access-token>
17
- * {
18
- * "oldPassword": "currentPassword123",
19
- * "newPassword": "newSecurePassword456"
20
- * }
21
- * ```
22
- */
23
-
24
- import { IsString, MinLength, MaxLength } from 'class-validator';
25
-
26
- export class ChangePasswordDTO {
27
- /**
28
- * Current password
29
- *
30
- * Validation:
31
- * - Must be a string
32
- *
33
- * Note: NOT trimmed (passwords can have leading/trailing spaces)
34
- */
35
- @IsString({ message: 'Old password must be a string' })
36
- oldPassword!: string;
37
-
38
- /**
39
- * New password
40
- *
41
- * Validation:
42
- * - Must be a string
43
- * - Min 8 characters (security requirement)
44
- * - Max 128 characters (prevents DoS via bcrypt)
45
- *
46
- * Note: NOT trimmed (passwords can have leading/trailing spaces)
47
- *
48
- * Additional checks in service layer:
49
- * - Password history (prevent reuse of recent passwords)
50
- * - Password strength (if configured)
51
- * - Not same as old password
52
- */
53
- @IsString({ message: 'New password must be a string' })
54
- @MinLength(8, { message: 'Password must be at least 8 characters' })
55
- @MaxLength(128, { message: 'Password must not exceed 128 characters' })
56
- newPassword!: string;
57
- }