@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,103 +0,0 @@
1
- /**
2
- * DTO for verifying MFA code
3
- *
4
- * Used to verify MFA code using the appropriate provider.
5
- * Routes verification to the correct provider based on method name.
6
- *
7
- * @example
8
- * ```typescript
9
- * const isValid = await mfaService.verifyCode({
10
- * sub: 'user-uuid',
11
- * methodName: 'totp',
12
- * code: '123456',
13
- * deviceId: 1
14
- * });
15
- * ```
16
- */
17
-
18
- import { IsEnum, IsString, IsUUID, IsOptional, MaxLength, IsInt } from 'class-validator';
19
- import { Transform } from 'class-transformer';
20
- import { MFAMethod } from '../enums/mfa-method.enum';
21
-
22
- /**
23
- * DTO for verifying MFA code
24
- */
25
- export class VerifyMFACodeDTO {
26
- /**
27
- * User's unique identifier (UUID v4)
28
- *
29
- * Validation:
30
- * - Must be a valid UUID v4 format
31
- * - Matches DB constraint: char(36) or uuid
32
- *
33
- * Sanitization:
34
- * - Trimmed
35
- * - Lowercased for consistency
36
- *
37
- * @example "a21b654c-2746-4168-acee-c175083a65cd"
38
- */
39
- @IsUUID('4', { message: 'User sub must be a valid UUID v4 format' })
40
- @Transform(({ value }) => {
41
- if (typeof value === 'string') {
42
- return value.trim().toLowerCase();
43
- }
44
- return value;
45
- })
46
- sub!: string;
47
-
48
- /**
49
- * MFA method name
50
- *
51
- * Validation:
52
- * - Must be one of: totp, sms, email, passkey, backup
53
- * - Max 50 characters
54
- *
55
- * Sanitization:
56
- * - Trimmed and lowercased
57
- *
58
- * @example "totp"
59
- */
60
- @IsString({ message: 'Method name must be a string' })
61
- @IsEnum([MFAMethod.TOTP, MFAMethod.SMS, MFAMethod.EMAIL, MFAMethod.PASSKEY, MFAMethod.BACKUP], {
62
- message: 'Method name must be one of: totp, sms, email, passkey, backup',
63
- })
64
- @MaxLength(50, { message: 'Method name must not exceed 50 characters' })
65
- @Transform(({ value }) => {
66
- if (typeof value === 'string') {
67
- return value.trim().toLowerCase();
68
- }
69
- return value;
70
- })
71
- methodName!: string;
72
-
73
- /**
74
- * Verification code or credential (provider-specific)
75
- *
76
- * Validation:
77
- * - Must be a string or object depending on method
78
- * - For TOTP/SMS/Email: string code
79
- * - For Passkey: credential object
80
- * - For Backup: string code
81
- */
82
- code!: string | Record<string, unknown>;
83
-
84
- /**
85
- * Optional device ID
86
- *
87
- * Validation:
88
- * - Must be a positive integer if provided
89
- */
90
- @IsOptional()
91
- @IsInt({ message: 'Device ID must be a number' })
92
- deviceId?: number;
93
- }
94
-
95
- /**
96
- * Response DTO for MFA code verification
97
- */
98
- export class VerifyMFACodeResponseDTO {
99
- /**
100
- * Whether verification succeeded
101
- */
102
- valid!: boolean;
103
- }
@@ -1,78 +0,0 @@
1
- import { IsUUID, IsNumberString, Length, IsOptional, IsInt, Min } from 'class-validator';
2
- import { Transform } from 'class-transformer';
3
-
4
- /**
5
- * Verify Phone with Code by User Sub DTO
6
- *
7
- * Used for phone verification with 6-digit OTP code when allowing duplicate phones.
8
- * Requires user sub to identify which user's phone to verify.
9
- *
10
- * Security:
11
- * - UUID format validated (prevents injection)
12
- * - Code format validated (6 digits)
13
- *
14
- * @example
15
- * ```typescript
16
- * POST /auth/verify-phone/verify-by-sub
17
- * {
18
- * "sub": "a21b654c-2746-4168-acee-c175083a65cd",
19
- * "code": "123456"
20
- * }
21
- * ```
22
- */
23
- export class VerifyPhoneWithCodeBySubDTO {
24
- /**
25
- * User's external identifier (sub/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 and lowercased for consistency
33
- *
34
- * @example "a21b654c-2746-4168-acee-c175083a65cd"
35
- */
36
- @IsUUID('4', { message: 'Sub must be a valid UUID v4 format' })
37
- @Transform(({ value }) => {
38
- if (typeof value === 'string') {
39
- return value.trim().toLowerCase();
40
- }
41
- return value;
42
- })
43
- sub!: string;
44
-
45
- /**
46
- * 6-digit verification code
47
- *
48
- * Validation:
49
- * - Must be a numeric string
50
- * - Exactly 6 digits
51
- *
52
- * @example "123456"
53
- */
54
- @IsNumberString({}, { message: 'Code must contain only digits' })
55
- @Length(6, 6, { message: 'Code must be exactly 6 digits' })
56
- @Transform(({ value }) => {
57
- if (typeof value === 'string') {
58
- const cleaned = value.replace(/\D/g, '');
59
- return cleaned.length === 6 ? cleaned : value;
60
- }
61
- return value;
62
- })
63
- code!: string;
64
-
65
- /**
66
- * Challenge session ID (internal use)
67
- * Optional - used internally to link verification to specific challenge session.
68
- * Provides security by ensuring codes are only valid for the session they were created for.
69
- *
70
- * Validation:
71
- * - Must be a positive integer if provided
72
- * - Optional (for backward compatibility and direct verification flows)
73
- */
74
- @IsOptional()
75
- @IsInt({ message: 'challengeSessionId must be an integer' })
76
- @Min(1, { message: 'challengeSessionId must be a positive integer' })
77
- challengeSessionId?: number;
78
- }
@@ -1,245 +0,0 @@
1
- import {
2
- IsString,
3
- IsNotEmpty,
4
- Length,
5
- Matches,
6
- MaxLength,
7
- IsNumberString,
8
- IsUUID,
9
- IsOptional,
10
- IsBoolean,
11
- IsInt,
12
- Min,
13
- } from 'class-validator';
14
- import { Transform } from 'class-transformer';
15
-
16
- /**
17
- * Verify Phone with Code DTO
18
- *
19
- * Used for phone verification with 6-digit OTP code.
20
- *
21
- * Security:
22
- * - Phone validated against E.164 format (prevents SQL injection)
23
- * - Code validated for exact 6 digits
24
- * - All fields match DB constraints
25
- *
26
- * @example
27
- * ```typescript
28
- * POST /auth/verify-phone/verify
29
- * {
30
- * "phone": "+1234567890",
31
- * "code": "123456"
32
- * }
33
- * ```
34
- */
35
- export class VerifyPhoneWithCodeDTO {
36
- /**
37
- * User's phone number in E.164 format
38
- *
39
- * Validation:
40
- * - Must be a string
41
- * - Must match E.164 format: +[country code][number]
42
- * - Max 20 characters (matches DB constraint: varchar(20))
43
- *
44
- * Sanitization:
45
- * - Trimmed
46
- * - Whitespace removed
47
- *
48
- * @example "+1234567890"
49
- */
50
- @IsString({ message: 'Phone must be a string' })
51
- @IsNotEmpty({ message: 'Phone is required' })
52
- @MaxLength(20, { message: 'Phone number must not exceed 20 characters' })
53
- @Matches(/^\+[1-9]\d{1,14}$/, {
54
- message: 'Phone must be in E.164 format (e.g., +1234567890)',
55
- })
56
- @Transform(({ value }) => {
57
- if (typeof value === 'string') {
58
- // Remove all whitespace and keep only digits and +
59
- return value.replace(/\s/g, '');
60
- }
61
- return value;
62
- })
63
- phone!: string;
64
-
65
- /**
66
- * 6-digit verification code
67
- *
68
- * Validation:
69
- * - Must be a string
70
- * - Exactly 6 digits (numeric only)
71
- * - No letters, spaces, or special characters
72
- * - Fixed length prevents timing attacks
73
- *
74
- * Sanitization:
75
- * - Removes all whitespace (users might copy "123 456")
76
- * - Ensures only numeric string
77
- *
78
- * @example "123456"
79
- */
80
- @IsNumberString({}, { message: 'Code must contain only digits' })
81
- @Length(6, 6, { message: 'Verification code must be exactly 6 digits' })
82
- @Transform(({ value }) => {
83
- if (typeof value === 'string') {
84
- // Remove all whitespace and non-digit characters
85
- const cleaned = value.replace(/\D/g, '');
86
- return cleaned.length === 6 ? cleaned : value; // Return original if not 6 digits (let validator catch it)
87
- }
88
- return value;
89
- })
90
- code!: string;
91
-
92
- /**
93
- * Challenge session ID (internal use)
94
- * Optional - used internally to link verification to specific challenge session.
95
- * Provides security by ensuring codes are only valid for the session they were created for.
96
- *
97
- * Validation:
98
- * - Must be a positive integer if provided
99
- * - Optional (for backward compatibility and direct verification flows)
100
- */
101
- @IsOptional()
102
- @IsInt({ message: 'challengeSessionId must be an integer' })
103
- @Min(1, { message: 'challengeSessionId must be a positive integer' })
104
- challengeSessionId?: number;
105
- }
106
-
107
- /**
108
- * DTO for sending verification SMS
109
- *
110
- * Security:
111
- * - User sub validated as UUID v4
112
- * - Skip flag is boolean (prevents injection)
113
- */
114
- export class SendVerificationSMSDTO {
115
- /**
116
- * User identifier (UUID v4)
117
- *
118
- * Validation:
119
- * - Must be valid UUID v4 format
120
- *
121
- * Sanitization:
122
- * - Trimmed and lowercased
123
- */
124
- @IsUUID('4', { message: 'User ID must be a valid UUID v4 format' })
125
- @Transform(({ value }) => {
126
- if (typeof value === 'string') {
127
- return value.trim().toLowerCase();
128
- }
129
- return value;
130
- })
131
- sub!: string;
132
-
133
- /**
134
- * Skip the "already verified" check
135
- * Used for MFA contexts where codes are needed even if phone is verified
136
- *
137
- * Validation:
138
- * - Must be boolean
139
- * - Optional (defaults to true)
140
- */
141
- @IsOptional()
142
- @IsBoolean({ message: 'skipAlreadyVerifiedCheck must be a boolean' })
143
- skipAlreadyVerifiedCheck?: boolean;
144
-
145
- /**
146
- * Challenge session ID to link this verification token to
147
- * Optional - for linking verification tokens to specific challenge sessions.
148
- * Provides security by preventing old tokens from being used with new sessions.
149
- *
150
- * Validation:
151
- * - Must be a positive integer
152
- * - Optional (for backward compatibility and non-challenge flows)
153
- */
154
- @IsOptional()
155
- @IsInt({ message: 'challengeSessionId must be an integer' })
156
- @Min(1, { message: 'challengeSessionId must be a positive integer' })
157
- challengeSessionId?: number;
158
- }
159
-
160
- /**
161
- * Response DTO for sendVerificationSMS
162
- */
163
- export class SendVerificationSMSResponseDTO {
164
- /**
165
- * Verification token ID (internal integer)
166
- */
167
- tokenId!: number;
168
- }
169
-
170
- /**
171
- * Response DTO for verifyPhoneWithCode and verifyPhoneWithCodeBySub
172
- */
173
- export class VerifyPhoneResponseDTO {
174
- /**
175
- * Success message
176
- */
177
- message!: string;
178
- }
179
-
180
- /**
181
- * DTO for resending verification SMS
182
- *
183
- * Supports both sub and phone-based resend
184
- *
185
- * Security:
186
- * - Either sub or phone must be provided (conditional validation)
187
- * - Rate limiting applied in service layer
188
- * - Input sanitization prevents abuse
189
- */
190
- export class ResendVerificationSMSDTO {
191
- /**
192
- * User identifier (UUID v4) - optional if phone provided
193
- *
194
- * Validation:
195
- * - Must be valid UUID v4 format if provided
196
- * - Required if phone is not provided
197
- *
198
- * Sanitization:
199
- * - Trimmed and lowercased
200
- */
201
- @IsOptional()
202
- @IsUUID('4', { message: 'User ID must be a valid UUID v4 format' })
203
- @Transform(({ value }) => {
204
- if (typeof value === 'string') {
205
- return value.trim().toLowerCase();
206
- }
207
- return value;
208
- })
209
- sub?: string;
210
-
211
- /**
212
- * User's phone number - optional if sub provided
213
- *
214
- * Validation:
215
- * - Must match E.164 format if provided
216
- * - Max 20 characters (DB limit)
217
- * - Required if sub is not provided
218
- *
219
- * Sanitization:
220
- * - Whitespace removed
221
- */
222
- @IsOptional()
223
- @IsString({ message: 'Phone must be a string' })
224
- @MaxLength(20, { message: 'Phone number must not exceed 20 characters' })
225
- @Matches(/^\+[1-9]\d{1,14}$/, {
226
- message: 'Phone must be in E.164 format (e.g., +1234567890)',
227
- })
228
- @Transform(({ value }) => {
229
- if (typeof value === 'string') {
230
- return value.replace(/\s/g, '');
231
- }
232
- return value;
233
- })
234
- phone?: string;
235
- }
236
-
237
- /**
238
- * Response DTO for resendVerificationSMS
239
- */
240
- export class ResendVerificationSMSResponseDTO {
241
- /**
242
- * Verification token ID (internal integer)
243
- */
244
- tokenId!: number;
245
- }
@@ -1,232 +0,0 @@
1
- import { AuthAuditEventType } from '../enums/auth-audit-event-type.enum';
2
-
3
- /**
4
- * Authentication Audit Event Status
5
- *
6
- * Classification of event outcomes for filtering and analysis.
7
- */
8
- export type AuthAuditEventStatus = 'SUCCESS' | 'FAILURE' | 'INFO' | 'SUSPICIOUS';
9
-
10
- /**
11
- * Base Authentication Audit Entity
12
- *
13
- * Core audit record with all fields and business logic.
14
- * Database adapters extend this class and add ORM-specific decorators.
15
- *
16
- * @remarks
17
- * This class is database-agnostic. TypeORM, Prisma, or other ORMs
18
- * extend this class in their respective packages.
19
- *
20
- * **Design Notes:**
21
- * - Only stores `userId` (integer internal ID) - no `userSub` duplication
22
- * - Risk tracking fields are infrastructure for future adaptive MFA (no business logic)
23
- * - All audit integrations are non-blocking (errors logged, don't throw)
24
- */
25
- export class BaseAuthAudit {
26
- /**
27
- * Internal audit record ID (auto-increment integer)
28
- */
29
- id!: number;
30
-
31
- /**
32
- * Internal user ID (foreign key to users table)
33
- * Uses integer for optimal performance in joins and lookups.
34
- * API methods accepting userSub will resolve to userId before querying.
35
- *
36
- * @remarks
37
- * No userSub field to avoid duplication. All queries use userId
38
- * for efficient database operations.
39
- */
40
- userId!: number;
41
-
42
- /**
43
- * Type of authentication/security event
44
- */
45
- eventType!: AuthAuditEventType;
46
-
47
- /**
48
- * Event classification status
49
- * - SUCCESS: Operation completed successfully
50
- * - FAILURE: Operation failed (login failed, verification failed, etc.)
51
- * - INFO: Informational event (profile update, device added, etc.)
52
- * - SUSPICIOUS: Security violation or suspicious activity detected
53
- */
54
- eventStatus!: AuthAuditEventStatus;
55
-
56
- // ============================================================================
57
- // Risk Assessment Fields (Infrastructure for Future Adaptive MFA)
58
- // ============================================================================
59
-
60
- /**
61
- * Risk factor score (0-100)
62
- * Calculated during adaptive MFA evaluation (future implementation).
63
- * null if not applicable (non-adaptive flows).
64
- *
65
- * @remarks
66
- * This is infrastructure for future adaptive MFA. The audit service
67
- * records risk data but does NOT calculate risk scores. Risk calculation
68
- * and adaptive MFA business logic will be implemented in future phases.
69
- */
70
- riskFactor?: number | null;
71
-
72
- /**
73
- * Risk factors that contributed to the risk score
74
- * Examples: ['new_device', 'new_ip', 'new_country', 'impossible_travel']
75
- *
76
- * @remarks
77
- * Infrastructure field for future adaptive MFA implementation.
78
- */
79
- riskFactors?: string[] | null;
80
-
81
- /**
82
- * Whether adaptive MFA was triggered for this event
83
- * true if MFA was conditionally required based on risk (future implementation).
84
- * null if not applicable.
85
- *
86
- * @remarks
87
- * Infrastructure field for future adaptive MFA implementation.
88
- */
89
- adaptiveMfaTriggered?: boolean | null;
90
-
91
- // ============================================================================
92
- // Client Information
93
- // ============================================================================
94
-
95
- /**
96
- * IP address where event occurred
97
- */
98
- ipAddress?: string | null;
99
-
100
- /**
101
- * Country from IP geolocation (optional, for geographic risk assessment)
102
- */
103
- ipCountry?: string | null;
104
-
105
- /**
106
- * City from IP geolocation (optional, for geographic risk assessment)
107
- */
108
- ipCity?: string | null;
109
-
110
- /**
111
- * Latitude from IP geolocation (optional, for impossible travel detection)
112
- */
113
- ipLatitude?: number | null;
114
-
115
- /**
116
- * Longitude from IP geolocation (optional, for impossible travel detection)
117
- */
118
- ipLongitude?: number | null;
119
-
120
- /**
121
- * User agent string
122
- */
123
- userAgent?: string | null;
124
-
125
- /**
126
- * Platform extracted from user agent
127
- * Examples: "iOS", "Android", "Windows", "macOS"
128
- */
129
- platform?: string | null;
130
-
131
- /**
132
- * Browser extracted from user agent
133
- * Examples: "Chrome", "Safari", "Firefox"
134
- */
135
- browser?: string | null;
136
-
137
- /**
138
- * Device identifier (UUID)
139
- * Unique identifier for the device/browser
140
- */
141
- deviceId?: string | null;
142
-
143
- /**
144
- * User-friendly device name
145
- * Examples: "iPhone 15 Pro", "Chrome on MacBook"
146
- */
147
- deviceName?: string | null;
148
-
149
- /**
150
- * Device type
151
- * Examples: "mobile", "desktop", "tablet"
152
- */
153
- deviceType?: string | null;
154
-
155
- // ============================================================================
156
- // Context Information
157
- // ============================================================================
158
-
159
- /**
160
- * Session ID (if event is related to a session)
161
- * Foreign key to sessions table
162
- */
163
- sessionId?: number | null;
164
-
165
- /**
166
- * Challenge session ID (if event is related to a challenge)
167
- * Foreign key to challenge_sessions table
168
- */
169
- challengeSessionId?: number | null;
170
-
171
- /**
172
- * Authentication method used
173
- * Examples: "password", "google", "apple", "facebook"
174
- * Used for social login provider tracking
175
- */
176
- authMethod?: string | null;
177
-
178
- /**
179
- * Who performed this action (for admin/CLI/automated operations)
180
- * - Admin user ID or email for manual admin actions
181
- * - CLI identifier for command-line operations
182
- * - 'system' for automated actions
183
- * - null for user-initiated actions
184
- *
185
- * @example
186
- * performedBy: 'admin@example.com'
187
- * performedBy: 'cli-migration-2025'
188
- * performedBy: 'system'
189
- */
190
- performedBy?: string | null;
191
-
192
- // ============================================================================
193
- // Event Details
194
- // ============================================================================
195
-
196
- /**
197
- * Reason for the event (optional)
198
- * Used for security events, account locks, etc.
199
- */
200
- reason?: string | null;
201
-
202
- /**
203
- * Detailed description of the event
204
- */
205
- description?: string | null;
206
-
207
- /**
208
- * Rich metadata (JSON)
209
- * Event-specific data stored without requiring schema changes.
210
- *
211
- * @example
212
- * ```typescript
213
- * // Social login
214
- * metadata: { provider: 'google', isNewUser: true }
215
- *
216
- * // Challenge event
217
- * metadata: { challengeName: 'VERIFY_EMAIL', challengeSessionId: 123 }
218
- *
219
- * // MFA device
220
- * metadata: { deviceType: 'totp', deviceName: 'iPhone Authenticator' }
221
- *
222
- * // Token reuse
223
- * metadata: { tokenFamily: 'abc123', action: 'token_family_revoked' }
224
- * ```
225
- */
226
- metadata?: Record<string, unknown> | null;
227
-
228
- /**
229
- * Timestamp when event occurred
230
- */
231
- createdAt!: Date;
232
- }