@veloxts/auth 0.3.3 → 0.3.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 (66) hide show
  1. package/README.md +1157 -30
  2. package/dist/__integration__/fixtures.d.ts +41 -0
  3. package/dist/__integration__/fixtures.d.ts.map +1 -0
  4. package/dist/__integration__/fixtures.js +79 -0
  5. package/dist/__integration__/fixtures.js.map +1 -0
  6. package/dist/__integration__/setup.d.ts +26 -0
  7. package/dist/__integration__/setup.d.ts.map +1 -0
  8. package/dist/__integration__/setup.js +28 -0
  9. package/dist/__integration__/setup.js.map +1 -0
  10. package/dist/adapter.d.ts +710 -0
  11. package/dist/adapter.d.ts.map +1 -0
  12. package/dist/adapter.js +581 -0
  13. package/dist/adapter.js.map +1 -0
  14. package/dist/adapters/better-auth.d.ts +271 -0
  15. package/dist/adapters/better-auth.d.ts.map +1 -0
  16. package/dist/adapters/better-auth.js +341 -0
  17. package/dist/adapters/better-auth.js.map +1 -0
  18. package/dist/adapters/index.d.ts +28 -0
  19. package/dist/adapters/index.d.ts.map +1 -0
  20. package/dist/adapters/index.js +28 -0
  21. package/dist/adapters/index.js.map +1 -0
  22. package/dist/csrf.d.ts +300 -0
  23. package/dist/csrf.d.ts.map +1 -0
  24. package/dist/csrf.js +402 -0
  25. package/dist/csrf.js.map +1 -0
  26. package/dist/guards.d.ts +142 -0
  27. package/dist/guards.d.ts.map +1 -0
  28. package/dist/guards.js +259 -0
  29. package/dist/guards.js.map +1 -0
  30. package/dist/hash.d.ts +91 -0
  31. package/dist/hash.d.ts.map +1 -0
  32. package/dist/hash.js +236 -0
  33. package/dist/hash.js.map +1 -0
  34. package/dist/index.d.ts +27 -32
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +94 -36
  37. package/dist/index.js.map +1 -1
  38. package/dist/jwt.d.ts +157 -0
  39. package/dist/jwt.d.ts.map +1 -0
  40. package/dist/jwt.js +489 -0
  41. package/dist/jwt.js.map +1 -0
  42. package/dist/middleware.d.ts +99 -0
  43. package/dist/middleware.d.ts.map +1 -0
  44. package/dist/middleware.js +253 -0
  45. package/dist/middleware.js.map +1 -0
  46. package/dist/plugin.d.ts +125 -0
  47. package/dist/plugin.d.ts.map +1 -0
  48. package/dist/plugin.js +193 -0
  49. package/dist/plugin.js.map +1 -0
  50. package/dist/policies.d.ts +137 -0
  51. package/dist/policies.d.ts.map +1 -0
  52. package/dist/policies.js +240 -0
  53. package/dist/policies.js.map +1 -0
  54. package/dist/rate-limit.d.ts +231 -0
  55. package/dist/rate-limit.d.ts.map +1 -0
  56. package/dist/rate-limit.js +352 -0
  57. package/dist/rate-limit.js.map +1 -0
  58. package/dist/session.d.ts +500 -0
  59. package/dist/session.d.ts.map +1 -0
  60. package/dist/session.js +801 -0
  61. package/dist/session.js.map +1 -0
  62. package/dist/types.d.ts +261 -0
  63. package/dist/types.d.ts.map +1 -0
  64. package/dist/types.js +33 -0
  65. package/dist/types.js.map +1 -0
  66. package/package.json +61 -7
package/dist/jwt.js ADDED
@@ -0,0 +1,489 @@
1
+ /**
2
+ * JWT token utilities for @veloxts/auth
3
+ * @module auth/jwt
4
+ */
5
+ import { createHmac, randomBytes, timingSafeEqual } from 'node:crypto';
6
+ import { AuthError } from './types.js';
7
+ // ============================================================================
8
+ // Constants
9
+ // ============================================================================
10
+ const DEFAULT_ACCESS_EXPIRY = '15m';
11
+ const DEFAULT_REFRESH_EXPIRY = '7d';
12
+ /**
13
+ * Minimum JWT secret length (64 characters = 512 bits)
14
+ * HS256 requires at least 256 bits, but we require 512 for extra security margin
15
+ */
16
+ const MIN_SECRET_LENGTH = 64;
17
+ /**
18
+ * Minimum unique characters in secret for entropy validation
19
+ */
20
+ const MIN_SECRET_ENTROPY_CHARS = 16;
21
+ // ============================================================================
22
+ // Token Expiration Bounds (Security Phase 3.1)
23
+ // ============================================================================
24
+ /**
25
+ * Minimum access token expiry: 1 minute
26
+ * Shorter tokens increase security but may impact UX
27
+ */
28
+ const MIN_ACCESS_TOKEN_SECONDS = 60;
29
+ /**
30
+ * Maximum access token expiry: 1 hour
31
+ * Longer lived tokens are a security risk if stolen
32
+ */
33
+ const MAX_ACCESS_TOKEN_SECONDS = 60 * 60;
34
+ /**
35
+ * Minimum refresh token expiry: 1 hour
36
+ * Too short reduces usability
37
+ */
38
+ const MIN_REFRESH_TOKEN_SECONDS = 60 * 60;
39
+ /**
40
+ * Maximum refresh token expiry: 30 days
41
+ * Longer lived refresh tokens increase risk window
42
+ */
43
+ const MAX_REFRESH_TOKEN_SECONDS = 30 * 24 * 60 * 60;
44
+ /**
45
+ * Recommended maximum access token expiry: 15 minutes
46
+ * Beyond this, consider shorter lived tokens with refresh
47
+ */
48
+ const RECOMMENDED_MAX_ACCESS_SECONDS = 15 * 60;
49
+ /**
50
+ * Recommended maximum refresh token expiry: 7 days
51
+ */
52
+ const RECOMMENDED_MAX_REFRESH_SECONDS = 7 * 24 * 60 * 60;
53
+ /**
54
+ * Reserved JWT claims that cannot be overridden via additionalClaims
55
+ */
56
+ const RESERVED_JWT_CLAIMS = new Set([
57
+ 'sub',
58
+ 'iss',
59
+ 'aud',
60
+ 'exp',
61
+ 'iat',
62
+ 'jti',
63
+ 'nbf',
64
+ 'type',
65
+ 'email',
66
+ ]);
67
+ // ============================================================================
68
+ // JWT Implementation
69
+ // ============================================================================
70
+ /**
71
+ * Validates a time string format
72
+ * Supports: '1s', '15m', '1h', '7d', etc.
73
+ * Minimum valid value is '1s' (1 second)
74
+ *
75
+ * @returns true if valid, false otherwise
76
+ */
77
+ export function isValidTimespan(time) {
78
+ const match = time.match(/^(\d+)([smhd])$/);
79
+ if (!match) {
80
+ return false;
81
+ }
82
+ const value = parseInt(match[1], 10);
83
+ // Value must be at least 1
84
+ return value >= 1;
85
+ }
86
+ /**
87
+ * Parses time string to seconds
88
+ * Supports: '15m', '1h', '7d', '30d', etc.
89
+ */
90
+ export function parseTimeToSeconds(time) {
91
+ const match = time.match(/^(\d+)([smhd])$/);
92
+ if (!match) {
93
+ throw new AuthError(`Invalid time format: ${time}. Use format like '15m', '1h', '7d'`, 400, 'INVALID_TIME_FORMAT');
94
+ }
95
+ const value = parseInt(match[1], 10);
96
+ const unit = match[2];
97
+ switch (unit) {
98
+ case 's':
99
+ return value;
100
+ case 'm':
101
+ return value * 60;
102
+ case 'h':
103
+ return value * 60 * 60;
104
+ case 'd':
105
+ return value * 60 * 60 * 24;
106
+ default:
107
+ throw new AuthError(`Unknown time unit: ${unit}`, 400, 'INVALID_TIME_UNIT');
108
+ }
109
+ }
110
+ /**
111
+ * Base64url encode
112
+ */
113
+ function base64urlEncode(data) {
114
+ const base64 = Buffer.from(data).toString('base64');
115
+ return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
116
+ }
117
+ /**
118
+ * Base64url decode
119
+ */
120
+ function base64urlDecode(data) {
121
+ const base64 = data.replace(/-/g, '+').replace(/_/g, '/');
122
+ const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);
123
+ return Buffer.from(padded, 'base64').toString('utf8');
124
+ }
125
+ /**
126
+ * Create HMAC-SHA256 signature
127
+ */
128
+ function createSignature(data, secret) {
129
+ const hmac = createHmac('sha256', secret);
130
+ hmac.update(data);
131
+ return base64urlEncode(hmac.digest());
132
+ }
133
+ /**
134
+ * Generate a unique token ID
135
+ */
136
+ export function generateTokenId() {
137
+ return randomBytes(16).toString('hex');
138
+ }
139
+ /**
140
+ * Validates token expiration against security bounds
141
+ *
142
+ * @param accessExpiry - Access token expiry string (e.g., '15m')
143
+ * @param refreshExpiry - Refresh token expiry string (e.g., '7d')
144
+ * @throws Error if expiration times are outside security bounds
145
+ */
146
+ export function validateTokenExpiration(accessExpiry, refreshExpiry) {
147
+ const accessSeconds = parseTimeToSeconds(accessExpiry);
148
+ const refreshSeconds = parseTimeToSeconds(refreshExpiry);
149
+ // Validate access token bounds
150
+ if (accessSeconds < MIN_ACCESS_TOKEN_SECONDS) {
151
+ throw new AuthError(`Access token expiry (${accessExpiry} = ${accessSeconds}s) is below minimum of ` +
152
+ `${MIN_ACCESS_TOKEN_SECONDS}s (1 minute). Very short tokens cause excessive refreshes.`, 400, 'INVALID_TOKEN_EXPIRY');
153
+ }
154
+ if (accessSeconds > MAX_ACCESS_TOKEN_SECONDS) {
155
+ throw new AuthError(`Access token expiry (${accessExpiry} = ${accessSeconds}s) exceeds maximum of ` +
156
+ `${MAX_ACCESS_TOKEN_SECONDS}s (1 hour). Long-lived access tokens are a security risk.`, 400, 'INVALID_TOKEN_EXPIRY');
157
+ }
158
+ // Validate refresh token bounds
159
+ if (refreshSeconds < MIN_REFRESH_TOKEN_SECONDS) {
160
+ throw new AuthError(`Refresh token expiry (${refreshExpiry} = ${refreshSeconds}s) is below minimum of ` +
161
+ `${MIN_REFRESH_TOKEN_SECONDS}s (1 hour). Very short refresh tokens impact usability.`, 400, 'INVALID_TOKEN_EXPIRY');
162
+ }
163
+ if (refreshSeconds > MAX_REFRESH_TOKEN_SECONDS) {
164
+ throw new AuthError(`Refresh token expiry (${refreshExpiry} = ${refreshSeconds}s) exceeds maximum of ` +
165
+ `${MAX_REFRESH_TOKEN_SECONDS}s (30 days). Long-lived refresh tokens increase attack window.`, 400, 'INVALID_TOKEN_EXPIRY');
166
+ }
167
+ // Warn about exceeding recommended limits (non-fatal)
168
+ if (accessSeconds > RECOMMENDED_MAX_ACCESS_SECONDS) {
169
+ console.warn(`[Security] Access token expiry (${accessExpiry}) exceeds recommended maximum of 15 minutes. ` +
170
+ 'Consider using shorter-lived access tokens with refresh.');
171
+ }
172
+ if (refreshSeconds > RECOMMENDED_MAX_REFRESH_SECONDS) {
173
+ console.warn(`[Security] Refresh token expiry (${refreshExpiry}) exceeds recommended maximum of 7 days. ` +
174
+ 'Long-lived refresh tokens increase the window for token theft attacks.');
175
+ }
176
+ // Ensure refresh tokens outlive access tokens
177
+ if (refreshSeconds <= accessSeconds) {
178
+ throw new AuthError(`Refresh token expiry (${refreshExpiry} = ${refreshSeconds}s) must be longer than ` +
179
+ `access token expiry (${accessExpiry} = ${accessSeconds}s).`, 400, 'INVALID_TOKEN_EXPIRY');
180
+ }
181
+ }
182
+ // ============================================================================
183
+ // JWT Manager Class
184
+ // ============================================================================
185
+ /**
186
+ * JWT token manager
187
+ *
188
+ * Handles token creation, verification, and refresh.
189
+ * Uses HS256 (HMAC-SHA256) algorithm.
190
+ *
191
+ * @example
192
+ * ```typescript
193
+ * const jwt = new JwtManager({
194
+ * secret: process.env.JWT_SECRET!,
195
+ * accessTokenExpiry: '15m',
196
+ * refreshTokenExpiry: '7d',
197
+ * });
198
+ *
199
+ * // Create tokens for user
200
+ * const tokens = jwt.createTokenPair(user);
201
+ *
202
+ * // Verify access token
203
+ * const payload = jwt.verifyToken(tokens.accessToken);
204
+ *
205
+ * // Refresh tokens
206
+ * const newTokens = jwt.refreshTokens(tokens.refreshToken);
207
+ * ```
208
+ */
209
+ export class JwtManager {
210
+ config;
211
+ constructor(config) {
212
+ // Validate secret length (Critical Fix #1)
213
+ if (!config.secret || config.secret.length < MIN_SECRET_LENGTH) {
214
+ throw new AuthError(`JWT secret must be at least ${MIN_SECRET_LENGTH} characters long (512 bits). ` +
215
+ 'Generate with: openssl rand -base64 64', 500, 'INVALID_JWT_SECRET');
216
+ }
217
+ // Validate secret entropy - check for sufficient unique characters
218
+ const uniqueChars = new Set(config.secret).size;
219
+ if (uniqueChars < MIN_SECRET_ENTROPY_CHARS) {
220
+ throw new AuthError(`JWT secret has insufficient entropy (only ${uniqueChars} unique characters). ` +
221
+ 'Use cryptographically random data with at least 16 unique characters.', 500, 'INVALID_JWT_SECRET');
222
+ }
223
+ // Validate accessTokenExpiry format if provided
224
+ if (config.accessTokenExpiry !== undefined && !isValidTimespan(config.accessTokenExpiry)) {
225
+ throw new AuthError(`Invalid accessTokenExpiry "${config.accessTokenExpiry}". ` +
226
+ `Use formats like "15m", "1h", "7d". Minimum is "1s".`, 400, 'INVALID_TOKEN_EXPIRY');
227
+ }
228
+ // Validate refreshTokenExpiry format if provided
229
+ if (config.refreshTokenExpiry !== undefined && !isValidTimespan(config.refreshTokenExpiry)) {
230
+ throw new AuthError(`Invalid refreshTokenExpiry "${config.refreshTokenExpiry}". ` +
231
+ `Use formats like "15m", "1h", "7d". Minimum is "1s".`, 400, 'INVALID_TOKEN_EXPIRY');
232
+ }
233
+ // Store config with defaults
234
+ const accessExpiry = config.accessTokenExpiry ?? DEFAULT_ACCESS_EXPIRY;
235
+ const refreshExpiry = config.refreshTokenExpiry ?? DEFAULT_REFRESH_EXPIRY;
236
+ // Validate expiration bounds (Security Phase 3.1)
237
+ // This prevents developers from setting insecure expiration times
238
+ validateTokenExpiration(accessExpiry, refreshExpiry);
239
+ this.config = {
240
+ ...config,
241
+ accessTokenExpiry: accessExpiry,
242
+ refreshTokenExpiry: refreshExpiry,
243
+ };
244
+ }
245
+ /**
246
+ * Creates a JWT token with the given payload
247
+ *
248
+ * @param payload - Token payload (sub, email, type required)
249
+ * @param expiresIn - Expiration time string (e.g., '15m', '7d')
250
+ * @param options - Additional options
251
+ * @param options.notBefore - Delay in seconds before token becomes valid (default: 0)
252
+ */
253
+ createToken(payload, expiresIn, options) {
254
+ const now = Math.floor(Date.now() / 1000);
255
+ const exp = now + parseTimeToSeconds(expiresIn);
256
+ // Security Phase 3.3: Add not-before (nbf) claim
257
+ // nbf = issued at + optional delay (default: 0, meaning valid immediately)
258
+ const nbf = now + (options?.notBefore ?? 0);
259
+ const fullPayload = {
260
+ ...payload,
261
+ iat: now,
262
+ exp,
263
+ nbf, // Token is not valid before this time
264
+ };
265
+ // Create header
266
+ const header = { alg: 'HS256', typ: 'JWT' };
267
+ const encodedHeader = base64urlEncode(JSON.stringify(header));
268
+ const encodedPayload = base64urlEncode(JSON.stringify(fullPayload));
269
+ // Create signature
270
+ const signatureInput = `${encodedHeader}.${encodedPayload}`;
271
+ const signature = createSignature(signatureInput, this.config.secret);
272
+ return `${signatureInput}.${signature}`;
273
+ }
274
+ /**
275
+ * Verifies a JWT token and returns the payload
276
+ *
277
+ * @throws AuthError if token is invalid or expired
278
+ */
279
+ verifyToken(token) {
280
+ const parts = token.split('.');
281
+ if (parts.length !== 3) {
282
+ throw new AuthError('Invalid token format', 401, 'INVALID_TOKEN');
283
+ }
284
+ const [encodedHeader, encodedPayload, signature] = parts;
285
+ // Critical Fix #2: Validate algorithm BEFORE signature verification
286
+ // This prevents algorithm confusion attacks (CVE-2015-9235)
287
+ let header;
288
+ try {
289
+ header = JSON.parse(base64urlDecode(encodedHeader));
290
+ }
291
+ catch {
292
+ throw new AuthError('Invalid token header', 401, 'INVALID_TOKEN');
293
+ }
294
+ // Only allow HS256 - reject "none", RS256, and other algorithms
295
+ if (header.alg !== 'HS256') {
296
+ throw new AuthError(`Invalid algorithm: ${header.alg}. Only HS256 is supported.`, 401, 'INVALID_TOKEN');
297
+ }
298
+ if (header.typ !== 'JWT') {
299
+ throw new AuthError('Invalid token type in header', 401, 'INVALID_TOKEN');
300
+ }
301
+ // Verify signature using timing-safe comparison to prevent timing attacks
302
+ const signatureInput = `${encodedHeader}.${encodedPayload}`;
303
+ const expectedSignature = createSignature(signatureInput, this.config.secret);
304
+ const sigBuffer = Buffer.from(signature, 'utf8');
305
+ const expectedBuffer = Buffer.from(expectedSignature, 'utf8');
306
+ if (sigBuffer.length !== expectedBuffer.length || !timingSafeEqual(sigBuffer, expectedBuffer)) {
307
+ throw new AuthError('Invalid token signature', 401, 'INVALID_TOKEN');
308
+ }
309
+ // Decode payload
310
+ let payload;
311
+ try {
312
+ const decoded = JSON.parse(base64urlDecode(encodedPayload));
313
+ // Validate required fields
314
+ if (typeof decoded.sub !== 'string' ||
315
+ typeof decoded.email !== 'string' ||
316
+ typeof decoded.iat !== 'number' ||
317
+ typeof decoded.exp !== 'number' ||
318
+ (decoded.type !== 'access' && decoded.type !== 'refresh')) {
319
+ throw new AuthError('Missing required token fields', 401, 'INVALID_TOKEN');
320
+ }
321
+ payload = decoded;
322
+ }
323
+ catch (error) {
324
+ if (error instanceof AuthError) {
325
+ throw error;
326
+ }
327
+ throw new AuthError(error instanceof Error ? error.message : 'Invalid token payload', 401, 'INVALID_TOKEN');
328
+ }
329
+ // Check expiration
330
+ const now = Math.floor(Date.now() / 1000);
331
+ if (payload.exp < now) {
332
+ throw new AuthError('Token has expired', 401, 'TOKEN_EXPIRED');
333
+ }
334
+ // Check not-before claim if present (Medium Fix #10)
335
+ if (typeof payload.nbf === 'number' && payload.nbf > now) {
336
+ throw new AuthError('Token not yet valid', 401, 'TOKEN_NOT_YET_VALID');
337
+ }
338
+ // Verify issuer if configured
339
+ if (this.config.issuer && payload.iss !== this.config.issuer) {
340
+ throw new AuthError('Invalid token issuer', 401, 'INVALID_TOKEN');
341
+ }
342
+ // Verify audience if configured
343
+ if (this.config.audience && payload.aud !== this.config.audience) {
344
+ throw new AuthError('Invalid token audience', 401, 'INVALID_TOKEN');
345
+ }
346
+ return payload;
347
+ }
348
+ /**
349
+ * Creates an access/refresh token pair for a user
350
+ *
351
+ * @param user - The user to create tokens for
352
+ * @param additionalClaims - Custom claims to include (cannot override reserved claims)
353
+ * @throws AuthError if additionalClaims contains reserved JWT claims
354
+ */
355
+ createTokenPair(user, additionalClaims) {
356
+ // Critical Fix #3: Validate additionalClaims don't contain reserved claims
357
+ if (additionalClaims) {
358
+ for (const key of Object.keys(additionalClaims)) {
359
+ if (RESERVED_JWT_CLAIMS.has(key)) {
360
+ throw new AuthError(`Cannot override reserved JWT claim: ${key}. ` +
361
+ `Reserved claims are: ${[...RESERVED_JWT_CLAIMS].join(', ')}`, 400, 'INVALID_CLAIMS');
362
+ }
363
+ }
364
+ }
365
+ const tokenId = generateTokenId();
366
+ const basePayload = {
367
+ sub: user.id,
368
+ email: user.email,
369
+ jti: tokenId,
370
+ ...(this.config.issuer && { iss: this.config.issuer }),
371
+ ...(this.config.audience && { aud: this.config.audience }),
372
+ ...additionalClaims,
373
+ };
374
+ const accessToken = this.createToken({ ...basePayload, type: 'access' }, this.config.accessTokenExpiry);
375
+ const refreshToken = this.createToken({ ...basePayload, type: 'refresh' }, this.config.refreshTokenExpiry);
376
+ return {
377
+ accessToken,
378
+ refreshToken,
379
+ expiresIn: parseTimeToSeconds(this.config.accessTokenExpiry),
380
+ tokenType: 'Bearer',
381
+ };
382
+ }
383
+ refreshTokens(refreshToken, userLoader) {
384
+ const payload = this.verifyToken(refreshToken);
385
+ if (payload.type !== 'refresh') {
386
+ throw new AuthError('Invalid token type: expected refresh token', 401, 'INVALID_TOKEN');
387
+ }
388
+ // If userLoader provided, fetch fresh user data
389
+ if (userLoader) {
390
+ return userLoader(payload.sub).then((user) => {
391
+ if (!user) {
392
+ throw new AuthError('User not found', 401, 'USER_NOT_FOUND');
393
+ }
394
+ return this.createTokenPair(user);
395
+ });
396
+ }
397
+ // Otherwise, create new tokens from payload data
398
+ const user = {
399
+ id: payload.sub,
400
+ email: payload.email,
401
+ };
402
+ return this.createTokenPair(user);
403
+ }
404
+ /**
405
+ * Decodes a token without verification
406
+ * Useful for extracting payload from expired tokens
407
+ */
408
+ decodeToken(token) {
409
+ try {
410
+ const parts = token.split('.');
411
+ if (parts.length !== 3) {
412
+ return null;
413
+ }
414
+ return JSON.parse(base64urlDecode(parts[1]));
415
+ }
416
+ catch {
417
+ return null;
418
+ }
419
+ }
420
+ /**
421
+ * Extracts token from Authorization header
422
+ * Supports 'Bearer <token>' format
423
+ */
424
+ extractFromHeader(authHeader) {
425
+ if (!authHeader) {
426
+ return null;
427
+ }
428
+ const parts = authHeader.split(' ');
429
+ if (parts.length !== 2 || parts[0].toLowerCase() !== 'bearer') {
430
+ return null;
431
+ }
432
+ return parts[1];
433
+ }
434
+ }
435
+ /**
436
+ * Creates a new JWT manager instance (succinct API)
437
+ */
438
+ export function jwtManager(config) {
439
+ return new JwtManager(config);
440
+ }
441
+ /**
442
+ * Creates a new JWT manager instance
443
+ *
444
+ * @deprecated Use `jwtManager()` instead. Will be removed in v0.9.
445
+ */
446
+ export const createJwtManager = jwtManager;
447
+ /**
448
+ * Creates an in-memory token store for development and testing
449
+ *
450
+ * ⚠️ WARNING: NOT suitable for production!
451
+ * - Does not persist across server restarts
452
+ * - Does not work across multiple server instances
453
+ * - No automatic cleanup of expired token IDs
454
+ *
455
+ * For production, use Redis or database-backed storage:
456
+ * - upstash/redis for serverless
457
+ * - ioredis for traditional servers
458
+ * - Database table for audit trail
459
+ *
460
+ * @example
461
+ * ```typescript
462
+ * // Development/Testing
463
+ * const tokenStore = createInMemoryTokenStore();
464
+ *
465
+ * const authConfig: AuthConfig = {
466
+ * jwt: { secret: process.env.JWT_SECRET! },
467
+ * isTokenRevoked: tokenStore.isRevoked,
468
+ * };
469
+ *
470
+ * // Revoke on logout
471
+ * app.post('/logout', async (req) => {
472
+ * const tokenId = req.auth.token.jti;
473
+ * tokenStore.revoke(tokenId);
474
+ * });
475
+ * ```
476
+ */
477
+ export function createInMemoryTokenStore() {
478
+ const revokedTokens = new Set();
479
+ return {
480
+ revoke: (tokenId) => {
481
+ revokedTokens.add(tokenId);
482
+ },
483
+ isRevoked: (tokenId) => revokedTokens.has(tokenId),
484
+ clear: () => {
485
+ revokedTokens.clear();
486
+ },
487
+ };
488
+ }
489
+ //# sourceMappingURL=jwt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.js","sourceRoot":"","sources":["../src/jwt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Authentication middleware for @veloxts/auth
3
+ * @module auth/middleware
4
+ */
5
+ import type { BaseContext } from '@veloxts/core';
6
+ import type { MiddlewareFunction } from '@veloxts/router';
7
+ import { JwtManager } from './jwt.js';
8
+ import type { AuthConfig, AuthContext, AuthMiddlewareOptions, GuardDefinition, User } from './types.js';
9
+ /**
10
+ * Creates an authentication middleware for procedures (succinct API)
11
+ *
12
+ * This middleware:
13
+ * 1. Extracts JWT from Authorization header
14
+ * 2. Verifies the token
15
+ * 3. Loads user from database (if userLoader provided)
16
+ * 4. Adds user and auth context to ctx
17
+ * 5. Runs guards if specified
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const auth = authMiddleware(authConfig);
22
+ *
23
+ * // Use in procedures
24
+ * const getProfile = procedure()
25
+ * .use(auth.middleware())
26
+ * .query(async ({ ctx }) => {
27
+ * return ctx.user; // Guaranteed to exist
28
+ * });
29
+ *
30
+ * // Optional auth (user may be undefined)
31
+ * const getPosts = procedure()
32
+ * .use(auth.middleware({ optional: true }))
33
+ * .query(async ({ ctx }) => {
34
+ * // ctx.user may be undefined
35
+ * return fetchPosts(ctx.user?.id);
36
+ * });
37
+ *
38
+ * // With guards
39
+ * const adminOnly = procedure()
40
+ * .use(auth.middleware({ guards: [hasRole('admin')] }))
41
+ * .query(async ({ ctx }) => {
42
+ * // Only admins get here
43
+ * });
44
+ * ```
45
+ */
46
+ export declare function authMiddleware(config: AuthConfig): {
47
+ middleware: <TInput, TContext extends BaseContext, TOutput>(options?: AuthMiddlewareOptions) => MiddlewareFunction<TInput, TContext, TContext & {
48
+ user?: User;
49
+ auth: AuthContext;
50
+ }, TOutput>;
51
+ requireAuth: <TInput, TContext extends BaseContext, TOutput>(guards?: Array<GuardDefinition | string>) => MiddlewareFunction<TInput, TContext, TContext & {
52
+ user: User;
53
+ auth: AuthContext;
54
+ }, TOutput>;
55
+ optionalAuth: <TInput, TContext extends BaseContext, TOutput>() => MiddlewareFunction<TInput, TContext, TContext & {
56
+ user?: User;
57
+ auth: AuthContext;
58
+ }, TOutput>;
59
+ jwt: JwtManager;
60
+ };
61
+ /**
62
+ * Creates an authentication middleware for procedures
63
+ *
64
+ * @deprecated Use `authMiddleware()` instead. Will be removed in v0.9.
65
+ */
66
+ export declare const createAuthMiddleware: typeof authMiddleware;
67
+ /**
68
+ * Creates a rate limiting middleware (succinct API)
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * const rateLimit = rateLimitMiddleware({
73
+ * max: 100,
74
+ * windowMs: 60000, // 1 minute
75
+ * });
76
+ *
77
+ * const login = procedure()
78
+ * .use(rateLimit)
79
+ * .input(LoginSchema)
80
+ * .mutation(handler);
81
+ * ```
82
+ */
83
+ export declare function rateLimitMiddleware<TInput, TContext extends BaseContext, TOutput>(options: {
84
+ max?: number;
85
+ windowMs?: number;
86
+ keyGenerator?: (ctx: TContext) => string;
87
+ message?: string;
88
+ }): MiddlewareFunction<TInput, TContext, TContext, TOutput>;
89
+ /**
90
+ * Creates a rate limiting middleware
91
+ *
92
+ * @deprecated Use `rateLimitMiddleware()` instead. Will be removed in v0.9.
93
+ */
94
+ export declare const createRateLimitMiddleware: typeof rateLimitMiddleware;
95
+ /**
96
+ * Clears rate limit store (useful for testing)
97
+ */
98
+ export declare function clearRateLimitStore(): void;
99
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAG1D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,qBAAqB,EACrB,eAAe,EAEf,IAAI,EACL,MAAM,YAAY,CAAC;AAOpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU;iBAM3B,MAAM,EAAE,QAAQ,SAAS,WAAW,EAAE,OAAO,YACtD,qBAAqB,KAC7B,kBAAkB,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG;QAAE,IAAI,CAAC,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,EAAE,OAAO,CAAC;kBA8H1E,MAAM,EAAE,QAAQ,SAAS,WAAW,EAAE,OAAO,WACvD,KAAK,CAAC,eAAe,GAAG,MAAM,CAAC,KACvC,kBAAkB,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,EAAE,OAAO,CAAC;mBAYxE,MAAM,EAAE,QAAQ,SAAS,WAAW,EAAE,OAAO,OAAK,kBAAkB,CACxF,MAAM,EACN,QAAQ,EACR,QAAQ,GAAG;QAAE,IAAI,CAAC,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,EAC7C,OAAO,CACR;;EAUF;AAED;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,uBAAiB,CAAC;AAkBnD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,QAAQ,SAAS,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE;IAC1F,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,MAAM,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,kBAAkB,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,CAuC1D;AAED;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,4BAAsB,CAAC;AAE7D;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C"}