@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.
- package/README.md +1157 -30
- package/dist/__integration__/fixtures.d.ts +41 -0
- package/dist/__integration__/fixtures.d.ts.map +1 -0
- package/dist/__integration__/fixtures.js +79 -0
- package/dist/__integration__/fixtures.js.map +1 -0
- package/dist/__integration__/setup.d.ts +26 -0
- package/dist/__integration__/setup.d.ts.map +1 -0
- package/dist/__integration__/setup.js +28 -0
- package/dist/__integration__/setup.js.map +1 -0
- package/dist/adapter.d.ts +710 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +581 -0
- package/dist/adapter.js.map +1 -0
- package/dist/adapters/better-auth.d.ts +271 -0
- package/dist/adapters/better-auth.d.ts.map +1 -0
- package/dist/adapters/better-auth.js +341 -0
- package/dist/adapters/better-auth.js.map +1 -0
- package/dist/adapters/index.d.ts +28 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +28 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/csrf.d.ts +300 -0
- package/dist/csrf.d.ts.map +1 -0
- package/dist/csrf.js +402 -0
- package/dist/csrf.js.map +1 -0
- package/dist/guards.d.ts +142 -0
- package/dist/guards.d.ts.map +1 -0
- package/dist/guards.js +259 -0
- package/dist/guards.js.map +1 -0
- package/dist/hash.d.ts +91 -0
- package/dist/hash.d.ts.map +1 -0
- package/dist/hash.js +236 -0
- package/dist/hash.js.map +1 -0
- package/dist/index.d.ts +27 -32
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +94 -36
- package/dist/index.js.map +1 -1
- package/dist/jwt.d.ts +157 -0
- package/dist/jwt.d.ts.map +1 -0
- package/dist/jwt.js +489 -0
- package/dist/jwt.js.map +1 -0
- package/dist/middleware.d.ts +99 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +253 -0
- package/dist/middleware.js.map +1 -0
- package/dist/plugin.d.ts +125 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +193 -0
- package/dist/plugin.js.map +1 -0
- package/dist/policies.d.ts +137 -0
- package/dist/policies.d.ts.map +1 -0
- package/dist/policies.js +240 -0
- package/dist/policies.js.map +1 -0
- package/dist/rate-limit.d.ts +231 -0
- package/dist/rate-limit.d.ts.map +1 -0
- package/dist/rate-limit.js +352 -0
- package/dist/rate-limit.js.map +1 -0
- package/dist/session.d.ts +500 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +801 -0
- package/dist/session.js.map +1 -0
- package/dist/types.d.ts +261 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +33 -0
- package/dist/types.js.map +1 -0
- package/package.json +61 -7
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication-specific rate limiting
|
|
3
|
+
*
|
|
4
|
+
* Provides specialized rate limiters for authentication endpoints with:
|
|
5
|
+
* - Per-email+IP tracking (prevents brute force on specific accounts)
|
|
6
|
+
* - Account lockout detection
|
|
7
|
+
* - Separate limits for login, register, and password reset
|
|
8
|
+
* - Progressive backoff support
|
|
9
|
+
*
|
|
10
|
+
* @module auth/rate-limit
|
|
11
|
+
*/
|
|
12
|
+
import { AuthError } from './types.js';
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Rate Limit Store
|
|
15
|
+
// ============================================================================
|
|
16
|
+
/**
|
|
17
|
+
* In-memory rate limit store
|
|
18
|
+
*
|
|
19
|
+
* PRODUCTION NOTE: Replace with Redis for horizontal scaling:
|
|
20
|
+
* ```typescript
|
|
21
|
+
* import Redis from 'ioredis';
|
|
22
|
+
* const redis = new Redis(process.env.REDIS_URL);
|
|
23
|
+
*
|
|
24
|
+
* // Store entry as JSON with TTL
|
|
25
|
+
* await redis.setex(`ratelimit:${key}`, ttlSeconds, JSON.stringify(entry));
|
|
26
|
+
*
|
|
27
|
+
* // Get entry
|
|
28
|
+
* const data = await redis.get(`ratelimit:${key}`);
|
|
29
|
+
* const entry = data ? JSON.parse(data) : null;
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
const authRateLimitStore = new Map();
|
|
33
|
+
/**
|
|
34
|
+
* Cleanup interval reference
|
|
35
|
+
*/
|
|
36
|
+
let cleanupInterval = null;
|
|
37
|
+
/**
|
|
38
|
+
* Start periodic cleanup of expired entries
|
|
39
|
+
*/
|
|
40
|
+
function startCleanup() {
|
|
41
|
+
if (cleanupInterval)
|
|
42
|
+
return;
|
|
43
|
+
cleanupInterval = setInterval(() => {
|
|
44
|
+
const now = Date.now();
|
|
45
|
+
for (const [key, entry] of authRateLimitStore.entries()) {
|
|
46
|
+
// Remove if both window and lockout have expired
|
|
47
|
+
const windowExpired = entry.windowResetAt <= now;
|
|
48
|
+
const lockoutExpired = !entry.lockoutUntil || entry.lockoutUntil <= now;
|
|
49
|
+
if (windowExpired && lockoutExpired) {
|
|
50
|
+
authRateLimitStore.delete(key);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}, 60000); // Run every minute
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Stop cleanup interval (for testing)
|
|
57
|
+
*/
|
|
58
|
+
export function stopAuthRateLimitCleanup() {
|
|
59
|
+
if (cleanupInterval) {
|
|
60
|
+
clearInterval(cleanupInterval);
|
|
61
|
+
cleanupInterval = null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Clear all rate limit entries (for testing)
|
|
66
|
+
*/
|
|
67
|
+
export function clearAuthRateLimitStore() {
|
|
68
|
+
authRateLimitStore.clear();
|
|
69
|
+
}
|
|
70
|
+
// Start cleanup on module load
|
|
71
|
+
startCleanup();
|
|
72
|
+
// ============================================================================
|
|
73
|
+
// Auth Rate Limiter
|
|
74
|
+
// ============================================================================
|
|
75
|
+
/**
|
|
76
|
+
* Creates an authentication rate limiter
|
|
77
|
+
*
|
|
78
|
+
* This factory returns rate limit middlewares configured for different
|
|
79
|
+
* auth operations with sensible defaults.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* const authRateLimiter = createAuthRateLimiter({
|
|
84
|
+
* login: { maxAttempts: 5, windowMs: 15 * 60 * 1000 },
|
|
85
|
+
* register: { maxAttempts: 3, windowMs: 60 * 60 * 1000 },
|
|
86
|
+
* });
|
|
87
|
+
*
|
|
88
|
+
* // Apply to procedures
|
|
89
|
+
* const login = procedure()
|
|
90
|
+
* .use(authRateLimiter.login(ctx => ctx.input.email))
|
|
91
|
+
* .mutation(loginHandler);
|
|
92
|
+
*
|
|
93
|
+
* const register = procedure()
|
|
94
|
+
* .use(authRateLimiter.register())
|
|
95
|
+
* .mutation(registerHandler);
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
export function createAuthRateLimiter(config = {}) {
|
|
99
|
+
// Default configurations
|
|
100
|
+
const loginConfig = {
|
|
101
|
+
maxAttempts: config.login?.maxAttempts ?? 5,
|
|
102
|
+
windowMs: config.login?.windowMs ?? 15 * 60 * 1000, // 15 minutes
|
|
103
|
+
lockoutDurationMs: config.login?.lockoutDurationMs ?? 15 * 60 * 1000,
|
|
104
|
+
keyGenerator: config.login?.keyGenerator ?? defaultKeyGenerator,
|
|
105
|
+
message: config.login?.message ?? 'Too many login attempts. Please try again later.',
|
|
106
|
+
progressiveBackoff: config.login?.progressiveBackoff ?? true,
|
|
107
|
+
};
|
|
108
|
+
const registerConfig = {
|
|
109
|
+
maxAttempts: config.register?.maxAttempts ?? 3,
|
|
110
|
+
windowMs: config.register?.windowMs ?? 60 * 60 * 1000, // 1 hour
|
|
111
|
+
lockoutDurationMs: config.register?.lockoutDurationMs ?? 60 * 60 * 1000,
|
|
112
|
+
keyGenerator: config.register?.keyGenerator ?? ((ctx) => ctx.request.ip ?? 'unknown'),
|
|
113
|
+
message: config.register?.message ?? 'Too many registration attempts. Please try again later.',
|
|
114
|
+
progressiveBackoff: config.register?.progressiveBackoff ?? false,
|
|
115
|
+
};
|
|
116
|
+
const passwordResetConfig = {
|
|
117
|
+
maxAttempts: config.passwordReset?.maxAttempts ?? 3,
|
|
118
|
+
windowMs: config.passwordReset?.windowMs ?? 60 * 60 * 1000, // 1 hour
|
|
119
|
+
lockoutDurationMs: config.passwordReset?.lockoutDurationMs ?? 60 * 60 * 1000,
|
|
120
|
+
keyGenerator: config.passwordReset?.keyGenerator ?? ((ctx) => ctx.request.ip ?? 'unknown'),
|
|
121
|
+
message: config.passwordReset?.message ?? 'Too many password reset attempts. Please try again later.',
|
|
122
|
+
progressiveBackoff: config.passwordReset?.progressiveBackoff ?? false,
|
|
123
|
+
};
|
|
124
|
+
const refreshConfig = {
|
|
125
|
+
maxAttempts: config.refresh?.maxAttempts ?? 10,
|
|
126
|
+
windowMs: config.refresh?.windowMs ?? 60 * 1000, // 1 minute
|
|
127
|
+
lockoutDurationMs: config.refresh?.lockoutDurationMs ?? 60 * 1000,
|
|
128
|
+
keyGenerator: config.refresh?.keyGenerator ?? ((ctx) => ctx.request.ip ?? 'unknown'),
|
|
129
|
+
message: config.refresh?.message ?? 'Too many token refresh attempts. Please try again later.',
|
|
130
|
+
progressiveBackoff: config.refresh?.progressiveBackoff ?? false,
|
|
131
|
+
};
|
|
132
|
+
return {
|
|
133
|
+
/**
|
|
134
|
+
* Rate limiter for login attempts
|
|
135
|
+
*
|
|
136
|
+
* @param identifierFn - Function to extract identifier (email) from context
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```typescript
|
|
140
|
+
* login: procedure()
|
|
141
|
+
* .use(authRateLimiter.login((ctx) => (ctx.input as { email: string }).email))
|
|
142
|
+
* .input(LoginSchema)
|
|
143
|
+
* .mutation(handler)
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
login: (identifierFn) => {
|
|
147
|
+
return createRateLimitMiddleware(loginConfig, 'login', identifierFn);
|
|
148
|
+
},
|
|
149
|
+
/**
|
|
150
|
+
* Rate limiter for registration attempts
|
|
151
|
+
* Uses IP-only by default (no identifier needed)
|
|
152
|
+
*/
|
|
153
|
+
register: () => {
|
|
154
|
+
return createRateLimitMiddleware(registerConfig, 'register');
|
|
155
|
+
},
|
|
156
|
+
/**
|
|
157
|
+
* Rate limiter for password reset requests
|
|
158
|
+
*
|
|
159
|
+
* @param identifierFn - Optional function to extract identifier (email)
|
|
160
|
+
*/
|
|
161
|
+
passwordReset: (identifierFn) => {
|
|
162
|
+
return createRateLimitMiddleware(passwordResetConfig, 'password-reset', identifierFn);
|
|
163
|
+
},
|
|
164
|
+
/**
|
|
165
|
+
* Rate limiter for token refresh
|
|
166
|
+
*/
|
|
167
|
+
refresh: () => {
|
|
168
|
+
return createRateLimitMiddleware(refreshConfig, 'refresh');
|
|
169
|
+
},
|
|
170
|
+
/**
|
|
171
|
+
* Record a failed attempt (call after authentication fails)
|
|
172
|
+
*
|
|
173
|
+
* This allows tracking failures even when rate limit hasn't been hit,
|
|
174
|
+
* enabling account lockout after X failed passwords.
|
|
175
|
+
*
|
|
176
|
+
* @param key - Rate limit key (usually IP:email or IP)
|
|
177
|
+
* @param operation - Operation type for key namespacing
|
|
178
|
+
*/
|
|
179
|
+
recordFailure: (key, operation) => {
|
|
180
|
+
const fullKey = `auth:${operation}:${key}`;
|
|
181
|
+
const config = operation === 'login'
|
|
182
|
+
? loginConfig
|
|
183
|
+
: operation === 'register'
|
|
184
|
+
? registerConfig
|
|
185
|
+
: passwordResetConfig;
|
|
186
|
+
const now = Date.now();
|
|
187
|
+
const entry = authRateLimitStore.get(fullKey);
|
|
188
|
+
if (!entry || entry.windowResetAt <= now) {
|
|
189
|
+
// Start new window
|
|
190
|
+
authRateLimitStore.set(fullKey, {
|
|
191
|
+
attempts: 1,
|
|
192
|
+
windowResetAt: now + config.windowMs,
|
|
193
|
+
lockoutUntil: null,
|
|
194
|
+
lockoutCount: entry?.lockoutCount ?? 0,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
// Increment in current window
|
|
199
|
+
entry.attempts++;
|
|
200
|
+
// Check if lockout should trigger
|
|
201
|
+
if (entry.attempts >= config.maxAttempts) {
|
|
202
|
+
const lockoutMultiplier = config.progressiveBackoff ? 2 ** entry.lockoutCount : 1;
|
|
203
|
+
entry.lockoutUntil = now + config.lockoutDurationMs * lockoutMultiplier;
|
|
204
|
+
entry.lockoutCount++;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
/**
|
|
209
|
+
* Reset rate limit for a key (call after successful auth)
|
|
210
|
+
*/
|
|
211
|
+
resetLimit: (key, operation) => {
|
|
212
|
+
const fullKey = `auth:${operation}:${key}`;
|
|
213
|
+
authRateLimitStore.delete(fullKey);
|
|
214
|
+
},
|
|
215
|
+
/**
|
|
216
|
+
* Check if a key is currently locked out
|
|
217
|
+
*/
|
|
218
|
+
isLockedOut: (key, operation) => {
|
|
219
|
+
const fullKey = `auth:${operation}:${key}`;
|
|
220
|
+
const entry = authRateLimitStore.get(fullKey);
|
|
221
|
+
if (!entry || !entry.lockoutUntil)
|
|
222
|
+
return false;
|
|
223
|
+
if (entry.lockoutUntil <= Date.now()) {
|
|
224
|
+
// Lockout expired
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
return true;
|
|
228
|
+
},
|
|
229
|
+
/**
|
|
230
|
+
* Get remaining attempts for a key
|
|
231
|
+
*/
|
|
232
|
+
getRemainingAttempts: (key, operation) => {
|
|
233
|
+
const fullKey = `auth:${operation}:${key}`;
|
|
234
|
+
const config = operation === 'login'
|
|
235
|
+
? loginConfig
|
|
236
|
+
: operation === 'register'
|
|
237
|
+
? registerConfig
|
|
238
|
+
: operation === 'refresh'
|
|
239
|
+
? refreshConfig
|
|
240
|
+
: passwordResetConfig;
|
|
241
|
+
const entry = authRateLimitStore.get(fullKey);
|
|
242
|
+
if (!entry || entry.windowResetAt <= Date.now()) {
|
|
243
|
+
return config.maxAttempts;
|
|
244
|
+
}
|
|
245
|
+
return Math.max(0, config.maxAttempts - entry.attempts);
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
// ============================================================================
|
|
250
|
+
// Internal Helpers
|
|
251
|
+
// ============================================================================
|
|
252
|
+
/**
|
|
253
|
+
* Default key generator combining IP and identifier
|
|
254
|
+
*/
|
|
255
|
+
function defaultKeyGenerator(ctx, identifier) {
|
|
256
|
+
const ip = ctx.request.ip ?? 'unknown';
|
|
257
|
+
return identifier ? `${ip}:${identifier.toLowerCase()}` : ip;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Creates the actual rate limit middleware
|
|
261
|
+
*/
|
|
262
|
+
function createRateLimitMiddleware(config, operation, identifierFn) {
|
|
263
|
+
return async ({ ctx, input, next }) => {
|
|
264
|
+
const now = Date.now();
|
|
265
|
+
// Generate rate limit key
|
|
266
|
+
const identifier = identifierFn ? identifierFn({ ...ctx, input }) : undefined;
|
|
267
|
+
const baseKey = config.keyGenerator(ctx, identifier);
|
|
268
|
+
const key = `auth:${operation}:${baseKey}`;
|
|
269
|
+
// Get or create entry
|
|
270
|
+
let entry = authRateLimitStore.get(key);
|
|
271
|
+
// Check if currently locked out
|
|
272
|
+
if (entry?.lockoutUntil && entry.lockoutUntil > now) {
|
|
273
|
+
const retryAfter = Math.ceil((entry.lockoutUntil - now) / 1000);
|
|
274
|
+
// Set headers
|
|
275
|
+
ctx.reply.header('X-RateLimit-Limit', String(config.maxAttempts));
|
|
276
|
+
ctx.reply.header('X-RateLimit-Remaining', '0');
|
|
277
|
+
ctx.reply.header('X-RateLimit-Reset', String(Math.ceil(entry.lockoutUntil / 1000)));
|
|
278
|
+
ctx.reply.header('Retry-After', String(retryAfter));
|
|
279
|
+
throw new AuthError(`${config.message} Try again in ${formatDuration(retryAfter * 1000)}.`, 429, 'RATE_LIMIT_EXCEEDED');
|
|
280
|
+
}
|
|
281
|
+
// Clean up expired window
|
|
282
|
+
if (entry && entry.windowResetAt <= now) {
|
|
283
|
+
// Preserve lockout count for progressive backoff
|
|
284
|
+
const lockoutCount = entry.lockoutCount;
|
|
285
|
+
entry = {
|
|
286
|
+
attempts: 0,
|
|
287
|
+
windowResetAt: now + config.windowMs,
|
|
288
|
+
lockoutUntil: null,
|
|
289
|
+
lockoutCount,
|
|
290
|
+
};
|
|
291
|
+
authRateLimitStore.set(key, entry);
|
|
292
|
+
}
|
|
293
|
+
// Initialize if no entry
|
|
294
|
+
if (!entry) {
|
|
295
|
+
entry = {
|
|
296
|
+
attempts: 0,
|
|
297
|
+
windowResetAt: now + config.windowMs,
|
|
298
|
+
lockoutUntil: null,
|
|
299
|
+
lockoutCount: 0,
|
|
300
|
+
};
|
|
301
|
+
authRateLimitStore.set(key, entry);
|
|
302
|
+
}
|
|
303
|
+
// Increment attempt count
|
|
304
|
+
entry.attempts++;
|
|
305
|
+
// Set rate limit headers
|
|
306
|
+
const remaining = Math.max(0, config.maxAttempts - entry.attempts);
|
|
307
|
+
ctx.reply.header('X-RateLimit-Limit', String(config.maxAttempts));
|
|
308
|
+
ctx.reply.header('X-RateLimit-Remaining', String(remaining));
|
|
309
|
+
ctx.reply.header('X-RateLimit-Reset', String(Math.ceil(entry.windowResetAt / 1000)));
|
|
310
|
+
// Check if limit exceeded
|
|
311
|
+
if (entry.attempts > config.maxAttempts) {
|
|
312
|
+
// Apply lockout
|
|
313
|
+
const lockoutMultiplier = config.progressiveBackoff ? 2 ** entry.lockoutCount : 1;
|
|
314
|
+
entry.lockoutUntil = now + config.lockoutDurationMs * lockoutMultiplier;
|
|
315
|
+
entry.lockoutCount++;
|
|
316
|
+
const retryAfter = Math.ceil((entry.lockoutUntil - now) / 1000);
|
|
317
|
+
ctx.reply.header('Retry-After', String(retryAfter));
|
|
318
|
+
throw new AuthError(`${config.message} Try again in ${formatDuration(retryAfter * 1000)}.`, 429, 'RATE_LIMIT_EXCEEDED');
|
|
319
|
+
}
|
|
320
|
+
return next();
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Format duration in human-readable form
|
|
325
|
+
*/
|
|
326
|
+
function formatDuration(ms) {
|
|
327
|
+
const seconds = Math.ceil(ms / 1000);
|
|
328
|
+
if (seconds < 60)
|
|
329
|
+
return `${seconds} second${seconds !== 1 ? 's' : ''}`;
|
|
330
|
+
const minutes = Math.ceil(seconds / 60);
|
|
331
|
+
if (minutes < 60)
|
|
332
|
+
return `${minutes} minute${minutes !== 1 ? 's' : ''}`;
|
|
333
|
+
const hours = Math.ceil(minutes / 60);
|
|
334
|
+
return `${hours} hour${hours !== 1 ? 's' : ''}`;
|
|
335
|
+
}
|
|
336
|
+
// ============================================================================
|
|
337
|
+
// Convenience Export
|
|
338
|
+
// ============================================================================
|
|
339
|
+
/**
|
|
340
|
+
* Pre-configured auth rate limiter with sensible defaults
|
|
341
|
+
*
|
|
342
|
+
* @example
|
|
343
|
+
* ```typescript
|
|
344
|
+
* import { authRateLimiter } from '@veloxts/auth';
|
|
345
|
+
*
|
|
346
|
+
* const login = procedure()
|
|
347
|
+
* .use(authRateLimiter.login((ctx) => ctx.input.email))
|
|
348
|
+
* .mutation(handler);
|
|
349
|
+
* ```
|
|
350
|
+
*/
|
|
351
|
+
export const authRateLimiter = createAuthRateLimiter();
|
|
352
|
+
//# sourceMappingURL=rate-limit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../src/rate-limit.ts"],"names":[],"mappings":"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"}
|