@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,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
|
-
}
|