@nauth-toolkit/core 0.1.0 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/LICENSE +90 -0
  2. package/README.md +9 -0
  3. package/package.json +8 -3
  4. package/jest.config.js +0 -15
  5. package/jest.setup.ts +0 -6
  6. package/src/adapters/database-columns.ts +0 -165
  7. package/src/adapters/express.adapter.ts +0 -385
  8. package/src/adapters/fastify.adapter.ts +0 -416
  9. package/src/adapters/index.ts +0 -16
  10. package/src/adapters/storage.factory.ts +0 -143
  11. package/src/bootstrap.ts +0 -374
  12. package/src/dto/auth-challenge.dto.ts +0 -231
  13. package/src/dto/auth-response.dto.ts +0 -253
  14. package/src/dto/challenge-response.dto.ts +0 -234
  15. package/src/dto/change-password-request.dto.ts +0 -50
  16. package/src/dto/change-password-response.dto.ts +0 -29
  17. package/src/dto/change-password.dto.ts +0 -57
  18. package/src/dto/error-response.dto.ts +0 -136
  19. package/src/dto/get-available-methods.dto.ts +0 -55
  20. package/src/dto/get-challenge-data-response.dto.ts +0 -28
  21. package/src/dto/get-challenge-data.dto.ts +0 -69
  22. package/src/dto/get-client-info.dto.ts +0 -104
  23. package/src/dto/get-device-token-response.dto.ts +0 -25
  24. package/src/dto/get-events-by-type.dto.ts +0 -76
  25. package/src/dto/get-ip-address-response.dto.ts +0 -24
  26. package/src/dto/get-mfa-status.dto.ts +0 -94
  27. package/src/dto/get-risk-assessment-history.dto.ts +0 -39
  28. package/src/dto/get-session-id-response.dto.ts +0 -25
  29. package/src/dto/get-setup-data-response.dto.ts +0 -31
  30. package/src/dto/get-setup-data.dto.ts +0 -75
  31. package/src/dto/get-suspicious-activity.dto.ts +0 -42
  32. package/src/dto/get-user-agent-response.dto.ts +0 -23
  33. package/src/dto/get-user-auth-history.dto.ts +0 -95
  34. package/src/dto/get-user-by-email.dto.ts +0 -61
  35. package/src/dto/get-user-by-id.dto.ts +0 -46
  36. package/src/dto/get-user-devices.dto.ts +0 -53
  37. package/src/dto/get-user-response.dto.ts +0 -17
  38. package/src/dto/has-provider.dto.ts +0 -56
  39. package/src/dto/index.ts +0 -57
  40. package/src/dto/is-trusted-device-response.dto.ts +0 -34
  41. package/src/dto/list-providers-response.dto.ts +0 -23
  42. package/src/dto/login.dto.ts +0 -95
  43. package/src/dto/logout-all-response.dto.ts +0 -24
  44. package/src/dto/logout-all.dto.ts +0 -65
  45. package/src/dto/logout-response.dto.ts +0 -25
  46. package/src/dto/logout.dto.ts +0 -64
  47. package/src/dto/refresh-token.dto.ts +0 -36
  48. package/src/dto/remove-devices.dto.ts +0 -85
  49. package/src/dto/resend-code-response.dto.ts +0 -32
  50. package/src/dto/resend-code.dto.ts +0 -51
  51. package/src/dto/reset-password.dto.ts +0 -115
  52. package/src/dto/respond-challenge.dto.ts +0 -272
  53. package/src/dto/set-mfa-exemption.dto.ts +0 -112
  54. package/src/dto/set-must-change-password-response.dto.ts +0 -27
  55. package/src/dto/set-must-change-password.dto.ts +0 -46
  56. package/src/dto/set-preferred-method.dto.ts +0 -80
  57. package/src/dto/setup-mfa.dto.ts +0 -98
  58. package/src/dto/signup.dto.ts +0 -174
  59. package/src/dto/social-auth.dto.ts +0 -422
  60. package/src/dto/trust-device-response.dto.ts +0 -30
  61. package/src/dto/trust-device.dto.ts +0 -9
  62. package/src/dto/update-user-attributes-request.dto.ts +0 -51
  63. package/src/dto/user-response.dto.ts +0 -138
  64. package/src/dto/user-update.dto.ts +0 -222
  65. package/src/dto/verify-email.dto.ts +0 -313
  66. package/src/dto/verify-mfa-code.dto.ts +0 -103
  67. package/src/dto/verify-phone-by-sub.dto.ts +0 -78
  68. package/src/dto/verify-phone.dto.ts +0 -245
  69. package/src/entities/auth-audit.entity.ts +0 -232
  70. package/src/entities/challenge-session.entity.ts +0 -116
  71. package/src/entities/index.ts +0 -29
  72. package/src/entities/login-attempt.entity.ts +0 -64
  73. package/src/entities/mfa-device.entity.ts +0 -151
  74. package/src/entities/rate-limit.entity.ts +0 -44
  75. package/src/entities/session.entity.ts +0 -180
  76. package/src/entities/social-account.entity.ts +0 -96
  77. package/src/entities/storage-lock.entity.ts +0 -39
  78. package/src/entities/trusted-device.entity.ts +0 -112
  79. package/src/entities/user.entity.ts +0 -243
  80. package/src/entities/verification-token.entity.ts +0 -141
  81. package/src/enums/auth-audit-event-type.enum.ts +0 -360
  82. package/src/enums/error-codes.enum.ts +0 -420
  83. package/src/enums/mfa-method.enum.ts +0 -97
  84. package/src/enums/risk-factor.enum.ts +0 -111
  85. package/src/exceptions/nauth.exception.ts +0 -231
  86. package/src/handlers/auth.handler.ts +0 -260
  87. package/src/handlers/client-info.handler.ts +0 -101
  88. package/src/handlers/csrf.handler.ts +0 -156
  89. package/src/handlers/token-delivery.handler.ts +0 -118
  90. package/src/index.ts +0 -118
  91. package/src/interfaces/client-info.interface.ts +0 -85
  92. package/src/interfaces/config.interface.ts +0 -2135
  93. package/src/interfaces/entities.interface.ts +0 -226
  94. package/src/interfaces/index.ts +0 -15
  95. package/src/interfaces/logger.interface.ts +0 -283
  96. package/src/interfaces/mfa-provider.interface.ts +0 -154
  97. package/src/interfaces/oauth.interface.ts +0 -148
  98. package/src/interfaces/provider.interface.ts +0 -47
  99. package/src/interfaces/social-auth-provider.interface.ts +0 -131
  100. package/src/interfaces/storage-adapter.interface.ts +0 -82
  101. package/src/interfaces/template.interface.ts +0 -510
  102. package/src/interfaces/token-verifier.interface.ts +0 -110
  103. package/src/internal.ts +0 -178
  104. package/src/platform/interfaces.ts +0 -299
  105. package/src/schemas/auth-config.schema.ts +0 -646
  106. package/src/services/adaptive-mfa-decision.service.spec.ts +0 -1058
  107. package/src/services/adaptive-mfa-decision.service.ts +0 -457
  108. package/src/services/auth-audit.service.spec.ts +0 -675
  109. package/src/services/auth-audit.service.ts +0 -558
  110. package/src/services/auth-challenge-helper.service.spec.ts +0 -3227
  111. package/src/services/auth-challenge-helper.service.ts +0 -825
  112. package/src/services/auth-flow-context-builder.service.ts +0 -520
  113. package/src/services/auth-flow-rules.ts +0 -202
  114. package/src/services/auth-flow-state-definitions.ts +0 -190
  115. package/src/services/auth-flow-state-machine.service.ts +0 -207
  116. package/src/services/auth-flow-state-machine.types.ts +0 -316
  117. package/src/services/auth.service.spec.ts +0 -4195
  118. package/src/services/auth.service.ts +0 -3727
  119. package/src/services/challenge.service.spec.ts +0 -1363
  120. package/src/services/challenge.service.ts +0 -696
  121. package/src/services/client-info.service.spec.ts +0 -572
  122. package/src/services/client-info.service.ts +0 -374
  123. package/src/services/csrf.service.ts +0 -54
  124. package/src/services/email-verification.service.spec.ts +0 -1229
  125. package/src/services/email-verification.service.ts +0 -578
  126. package/src/services/geo-location.service.spec.ts +0 -603
  127. package/src/services/geo-location.service.ts +0 -599
  128. package/src/services/index.ts +0 -13
  129. package/src/services/jwt.service.spec.ts +0 -882
  130. package/src/services/jwt.service.ts +0 -621
  131. package/src/services/mfa-base.service.spec.ts +0 -246
  132. package/src/services/mfa-base.service.ts +0 -611
  133. package/src/services/mfa.service.spec.ts +0 -693
  134. package/src/services/mfa.service.ts +0 -960
  135. package/src/services/password.service.spec.ts +0 -166
  136. package/src/services/password.service.ts +0 -309
  137. package/src/services/phone-verification.service.spec.ts +0 -1120
  138. package/src/services/phone-verification.service.ts +0 -751
  139. package/src/services/risk-detection.service.spec.ts +0 -1292
  140. package/src/services/risk-detection.service.ts +0 -1012
  141. package/src/services/risk-scoring.service.spec.ts +0 -204
  142. package/src/services/risk-scoring.service.ts +0 -131
  143. package/src/services/session.service.spec.ts +0 -1293
  144. package/src/services/session.service.ts +0 -803
  145. package/src/services/social-account.service.spec.ts +0 -725
  146. package/src/services/social-auth-base.service.spec.ts +0 -418
  147. package/src/services/social-auth-base.service.ts +0 -581
  148. package/src/services/social-auth.service.spec.ts +0 -238
  149. package/src/services/social-auth.service.ts +0 -436
  150. package/src/services/social-provider-registry.service.spec.ts +0 -238
  151. package/src/services/social-provider-registry.service.ts +0 -122
  152. package/src/services/trusted-device.service.spec.ts +0 -505
  153. package/src/services/trusted-device.service.ts +0 -339
  154. package/src/storage/account-lockout-storage.service.spec.ts +0 -310
  155. package/src/storage/account-lockout-storage.service.ts +0 -89
  156. package/src/storage/index.ts +0 -3
  157. package/src/storage/memory-storage.adapter.ts +0 -443
  158. package/src/storage/rate-limit-storage.service.spec.ts +0 -247
  159. package/src/storage/rate-limit-storage.service.ts +0 -38
  160. package/src/templates/html-template.engine.spec.ts +0 -161
  161. package/src/templates/html-template.engine.ts +0 -688
  162. package/src/templates/index.ts +0 -7
  163. package/src/utils/common-passwords.spec.ts +0 -230
  164. package/src/utils/common-passwords.ts +0 -170
  165. package/src/utils/context-storage.ts +0 -188
  166. package/src/utils/cookie-names.util.ts +0 -67
  167. package/src/utils/cookies.util.ts +0 -94
  168. package/src/utils/index.ts +0 -12
  169. package/src/utils/ip-extractor.spec.ts +0 -330
  170. package/src/utils/ip-extractor.ts +0 -220
  171. package/src/utils/nauth-logger.spec.ts +0 -388
  172. package/src/utils/nauth-logger.ts +0 -215
  173. package/src/utils/pii-redactor.spec.ts +0 -130
  174. package/src/utils/pii-redactor.ts +0 -288
  175. package/src/utils/setup/get-repositories.ts +0 -140
  176. package/src/utils/setup/init-services.ts +0 -422
  177. package/src/utils/setup/init-social.ts +0 -189
  178. package/src/utils/setup/init-storage.ts +0 -94
  179. package/src/utils/setup/register-mfa.ts +0 -165
  180. package/src/utils/setup/run-nauth-migrations.ts +0 -61
  181. package/src/utils/token-delivery-policy.ts +0 -38
  182. package/src/validators/template.validator.ts +0 -219
  183. package/tsconfig.json +0 -37
  184. package/tsconfig.lint.json +0 -6
@@ -1,374 +0,0 @@
1
- import { ClientInfo } from '../interfaces/client-info.interface';
2
- import { ContextStorage } from '../utils/context-storage';
3
- import {
4
- GetClientInfoResponseDTO,
5
- GetIpAddressResponseDTO,
6
- GetUserAgentResponseDTO,
7
- GetDeviceTokenResponseDTO,
8
- GetSessionIdResponseDTO,
9
- } from '../dto';
10
-
11
- /**
12
- * Client Info Service
13
- *
14
- * Provides transparent access to client information (IP address, user agent, device info)
15
- * from the current request context using async local storage.
16
- *
17
- * This service eliminates the need to pass IP addresses and user agents as parameters
18
- * to authentication methods. The library handles this automatically, just like AWS Cognito.
19
- *
20
- * **Key Features:**
21
- * - Transparent access to client metadata
22
- * - No parameters needed in service methods
23
- * - Works across async boundaries
24
- * - Type-safe with TypeScript
25
- * - Thread-safe with async local storage
26
- * - Platform-agnostic (no framework dependencies)
27
- *
28
- * **Usage:**
29
- * ```typescript
30
- * export class AuthService {
31
- * constructor(private clientInfoService: ClientInfoService) {}
32
- *
33
- * async login(dto: LoginDTO) {
34
- * // Get client info from context (no parameters needed!)
35
- * const clientInfo = this.clientInfoService.get();
36
- *
37
- * // Use it
38
- * logger.debug('IP Address:', clientInfo.ipAddress);
39
- * logger.debug('User Agent:', clientInfo.userAgent);
40
- * }
41
- * }
42
- * ```
43
- *
44
- * **Note:**
45
- * This service must be called within the context of an HTTP request.
46
- * If called outside a request context (e.g., cron jobs, CLI), it will
47
- * return a default ClientInfo object with 'unknown' values.
48
- */
49
- export class ClientInfoService {
50
- constructor() {
51
- // No dependencies - uses static ContextStorage
52
- }
53
-
54
- /**
55
- * Get client information from the current request context
56
- *
57
- * This method retrieves client metadata that was automatically extracted
58
- * by ClientInfoInterceptor and stored in async local storage.
59
- *
60
- * @returns Response DTO with client information
61
- *
62
- * @example
63
- * ```typescript
64
- * const result = this.clientInfoService.get();
65
- * logger.debug('IP Address:', result.ipAddress); // 192.168.1.100
66
- * logger.debug('User Agent:', result.userAgent); // Mozilla/5.0 ...
67
- * ```
68
- *
69
- * @example
70
- * ```typescript
71
- * // If called outside request context (e.g., cron job)
72
- * const result = this.clientInfoService.get();
73
- * logger.debug('IP Address:', result.ipAddress); // 'unknown'
74
- * ```
75
- */
76
- get(): GetClientInfoResponseDTO {
77
- const clientInfo = ContextStorage.get<ClientInfo>('CLIENT_INFO');
78
-
79
- // If no client info in context (e.g., cron job, CLI), return default
80
- if (!clientInfo) {
81
- return {
82
- ipAddress: 'unknown',
83
- userAgent: 'unknown',
84
- } as GetClientInfoResponseDTO;
85
- }
86
-
87
- return clientInfo as GetClientInfoResponseDTO;
88
- }
89
-
90
- /**
91
- * Get IP address from the current request context
92
- *
93
- * Convenience method to get just the IP address without the full ClientInfo object.
94
- *
95
- * @returns Response DTO with IP address
96
- *
97
- * @example
98
- * ```typescript
99
- * const result = this.clientInfoService.getIpAddress();
100
- * logger.debug('IP Address:', result.ipAddress); // 192.168.1.100
101
- * ```
102
- */
103
- getIpAddress(): GetIpAddressResponseDTO {
104
- return {
105
- ipAddress: this.get().ipAddress,
106
- };
107
- }
108
-
109
- /**
110
- * Get user agent from the current request context
111
- *
112
- * Convenience method to get just the user agent without the full ClientInfo object.
113
- *
114
- * @returns Response DTO with user agent
115
- *
116
- * @example
117
- * ```typescript
118
- * const result = this.clientInfoService.getUserAgent();
119
- * logger.debug('User Agent:', result.userAgent); // Mozilla/5.0 (Windows NT 10.0; Win64; x64)...
120
- * ```
121
- */
122
- getUserAgent(): GetUserAgentResponseDTO {
123
- return {
124
- userAgent: this.get().userAgent,
125
- };
126
- }
127
-
128
- /**
129
- * Get device token from the current request context
130
- *
131
- * Convenience method to get just the device token (for trusted device feature).
132
- *
133
- * @returns Response DTO with device token
134
- *
135
- * @example
136
- * ```typescript
137
- * const result = this.clientInfoService.getDeviceToken();
138
- * if (result.deviceToken) {
139
- * logger.debug('Device token:', result.deviceToken);
140
- * }
141
- * ```
142
- */
143
- getDeviceToken(): GetDeviceTokenResponseDTO {
144
- return {
145
- deviceToken: this.get().deviceToken,
146
- };
147
- }
148
-
149
- /**
150
- * Get device ID from the current request context (deprecated)
151
- *
152
- * @deprecated Use getDeviceToken() instead. deviceId was removed from ClientInfo for security.
153
- * @returns Always undefined (deviceId not available from clientInfo - use session.deviceId if needed)
154
- *
155
- * @example
156
- * ```typescript
157
- * const deviceId = this.clientInfoService.getDeviceId();
158
- * // Always returns undefined
159
- * ```
160
- */
161
- getDeviceId(): string | undefined {
162
- // deviceId removed from ClientInfo interface - use session.deviceId if needed
163
- return undefined;
164
- }
165
-
166
- /**
167
- * Get session ID from the current request context
168
- *
169
- * Convenience method to get just the session ID (extracted from JWT token after authentication).
170
- *
171
- * @returns Response DTO with session ID
172
- *
173
- * @example
174
- * ```typescript
175
- * const result = this.clientInfoService.getSessionId();
176
- * if (result.sessionId) {
177
- * logger.debug('Session ID:', result.sessionId);
178
- * }
179
- * ```
180
- */
181
- getSessionId(): GetSessionIdResponseDTO {
182
- return {
183
- sessionId: this.get().sessionId,
184
- };
185
- }
186
-
187
- /**
188
- * Get response object from the current request context
189
- *
190
- * Returns the HTTP response object that was stored by the framework interceptor.
191
- * Used internally by services to perform response operations like clearing cookies.
192
- *
193
- * @returns Response object with cookie manipulation methods, or null if not available
194
- * @internal - Used by core services, not by application code
195
- *
196
- * @example
197
- * ```typescript
198
- * const response = this.clientInfoService.getResponse();
199
- * if (response?.clearCookie) {
200
- * response.clearCookie('my_cookie');
201
- * }
202
- * ```
203
- */
204
- getResponse(): { clearCookie?: (name: string, options?: unknown) => void } | null {
205
- return ContextStorage.get<{ clearCookie?: (name: string, options?: unknown) => void }>('HTTP_RESPONSE') || null;
206
- }
207
-
208
- /**
209
- * Parse user-agent string to extract browser, platform, and device information
210
- *
211
- * This method is used internally by interceptors to populate ClientInfo.
212
- * Services should use ClientInfoService.get() to access parsed information.
213
- *
214
- * @param userAgent - User-agent string from HTTP request
215
- * @returns Parsed user-agent information
216
- * @internal - Used by interceptors, not by application code
217
- */
218
- parseUserAgent(userAgent?: string | null): {
219
- browser: string | null;
220
- platform: string | null;
221
- deviceType: 'desktop' | 'mobile' | 'tablet' | null;
222
- deviceName: string | null;
223
- } {
224
- if (!userAgent || typeof userAgent !== 'string' || userAgent.trim() === '') {
225
- return {
226
- browser: null,
227
- platform: null,
228
- deviceType: null,
229
- deviceName: null,
230
- };
231
- }
232
-
233
- const ua = userAgent.toLowerCase();
234
-
235
- // ============================================================================
236
- // Detect Device Type
237
- // ============================================================================
238
- let deviceType: 'desktop' | 'mobile' | 'tablet' | null = null;
239
-
240
- // Mobile devices
241
- if (/mobile|android|iphone|ipod|blackberry|opera|mini|windows\s+phone|palm|iemobile/i.test(ua)) {
242
- // Tablets
243
- if (/tablet|ipad|playbook|silk|kindle/i.test(ua)) {
244
- deviceType = 'tablet';
245
- } else {
246
- deviceType = 'mobile';
247
- }
248
- } else {
249
- deviceType = 'desktop';
250
- }
251
-
252
- // ============================================================================
253
- // Detect Platform/OS
254
- // ============================================================================
255
- let platform: string | null = null;
256
-
257
- if (/windows/i.test(ua)) {
258
- if (/windows nt 10/i.test(ua)) {
259
- platform = 'Windows 10';
260
- } else if (/windows nt 11/i.test(ua)) {
261
- platform = 'Windows 11';
262
- } else if (/windows nt 6.3/i.test(ua)) {
263
- platform = 'Windows 8.1';
264
- } else if (/windows nt 6.2/i.test(ua)) {
265
- platform = 'Windows 8';
266
- } else if (/windows nt 6.1/i.test(ua)) {
267
- platform = 'Windows 7';
268
- } else {
269
- platform = 'Windows';
270
- }
271
- } else if (/macintosh|mac os x/i.test(ua)) {
272
- const match = ua.match(/mac os x (\d+)[._](\d+)/);
273
- if (match) {
274
- const major = parseInt(match[1], 10);
275
- // Convert to macOS version names (approximate)
276
- if (major >= 13) {
277
- platform = 'macOS Ventura+';
278
- } else if (major >= 12) {
279
- platform = 'macOS Monterey';
280
- } else if (major >= 11) {
281
- platform = 'macOS Big Sur';
282
- } else {
283
- platform = 'macOS';
284
- }
285
- } else {
286
- platform = 'macOS';
287
- }
288
- } else if (/iphone|ipad|ipod/i.test(ua)) {
289
- const match = ua.match(/os (\d+)[._](\d+)/);
290
- if (match) {
291
- platform = `iOS ${match[1]}.${match[2]}`;
292
- } else {
293
- platform = 'iOS';
294
- }
295
- } else if (/android/i.test(ua)) {
296
- const match = ua.match(/android (\d+)[._](\d+)/);
297
- if (match) {
298
- platform = `Android ${match[1]}.${match[2]}`;
299
- } else {
300
- platform = 'Android';
301
- }
302
- } else if (/linux/i.test(ua)) {
303
- platform = 'Linux';
304
- } else if (/ubuntu/i.test(ua)) {
305
- platform = 'Ubuntu';
306
- } else if (/fedora/i.test(ua)) {
307
- platform = 'Fedora';
308
- } else {
309
- platform = null;
310
- }
311
-
312
- // ============================================================================
313
- // Detect Browser
314
- // ============================================================================
315
- let browser: string | null = null;
316
-
317
- if (/edg/i.test(ua)) {
318
- browser = 'Edge';
319
- } else if (/chrome/i.test(ua) && !/edg/i.test(ua)) {
320
- const match = ua.match(/chrome\/(\d+)/);
321
- browser = match ? `Chrome ${match[1]}` : 'Chrome';
322
- } else if (/safari/i.test(ua) && !/chrome/i.test(ua)) {
323
- const match = ua.match(/version\/(\d+)/);
324
- browser = match ? `Safari ${match[1]}` : 'Safari';
325
- } else if (/firefox/i.test(ua)) {
326
- const match = ua.match(/firefox\/(\d+)/);
327
- browser = match ? `Firefox ${match[1]}` : 'Firefox';
328
- } else if (/opera|opr/i.test(ua)) {
329
- browser = 'Opera';
330
- } else if (/msie|trident/i.test(ua)) {
331
- browser = 'Internet Explorer';
332
- } else if (/brave/i.test(ua)) {
333
- browser = 'Brave';
334
- } else {
335
- browser = null;
336
- }
337
-
338
- // ============================================================================
339
- // Generate Device Name
340
- // ============================================================================
341
- let deviceName: string | null = null;
342
-
343
- if (browser && platform) {
344
- deviceName = `${browser} on ${platform}`;
345
- } else if (browser) {
346
- deviceName = browser;
347
- } else if (platform) {
348
- deviceName = platform;
349
- }
350
-
351
- // Special cases for mobile devices
352
- if (deviceType === 'mobile' || deviceType === 'tablet') {
353
- if (/iphone/i.test(ua)) {
354
- const modelMatch = ua.match(/iphone(\d+),?(\d+)?/);
355
- if (modelMatch) {
356
- deviceName = `iPhone ${modelMatch[1]}${modelMatch[2] ? ` ${modelMatch[2]}` : ''} on ${platform || 'iOS'}`;
357
- } else {
358
- deviceName = `iPhone on ${platform || 'iOS'}`;
359
- }
360
- } else if (/ipad/i.test(ua)) {
361
- deviceName = `iPad on ${platform || 'iOS'}`;
362
- } else if (/android/i.test(ua)) {
363
- deviceName = `${browser || 'Android'} on ${platform || 'Android'}`;
364
- }
365
- }
366
-
367
- return {
368
- browser,
369
- platform,
370
- deviceType,
371
- deviceName,
372
- };
373
- }
374
- }
@@ -1,54 +0,0 @@
1
- /**
2
- * CSRF Protection Service
3
- *
4
- * Handles CSRF token generation and validation for cookie-based authentication.
5
- * Uses cryptographically secure random tokens.
6
- */
7
-
8
- import * as crypto from 'crypto';
9
- import { NAuthConfig } from '../index';
10
-
11
- export class CsrfService {
12
- private readonly cookieName: string;
13
- private readonly headerName: string;
14
- private readonly cookieOptions: any;
15
-
16
- constructor(config: NAuthConfig) {
17
- this.cookieName = config.security?.csrf?.cookieName || 'nauth_csrf_token';
18
- this.headerName = config.security?.csrf?.headerName || 'x-csrf-token';
19
- this.cookieOptions = config.security?.csrf?.cookieOptions || {};
20
- }
21
-
22
- /**
23
- * Generate a new CSRF token
24
- * @returns Random 32-byte token as hex string
25
- */
26
- generateToken(): string {
27
- return crypto.randomBytes(32).toString('hex');
28
- }
29
-
30
- /**
31
- * Validate CSRF token
32
- * Compares token from request header with token from cookie.
33
- * Uses constant-time comparison to prevent timing attacks.
34
- */
35
- validateToken(headerToken: string, cookieToken: string): boolean {
36
- if (!headerToken || !cookieToken) {
37
- return false;
38
- }
39
- // Constant-time comparison
40
- return crypto.timingSafeEqual(Buffer.from(headerToken), Buffer.from(cookieToken));
41
- }
42
-
43
- getCookieName(): string {
44
- return this.cookieName;
45
- }
46
-
47
- getHeaderName(): string {
48
- return this.headerName;
49
- }
50
-
51
- getCookieOptions(): any {
52
- return this.cookieOptions;
53
- }
54
- }