Rate Limiting
The Auth class includes an InMemoryRateLimiter that limits failed login
attempts. It is enabled by default at 5 attempts per minute per email key.
How it works
Section titled “How it works”When a login() call via the credentials provider fails (wrong password or
user not found), the rate limiter counts the failure for that email. After 5
failures within a minute, the key is locked out and login() throws
UnauthorizedError.
try { const result = await auth.login("credentials", { email, password });} catch (e) { if (e instanceof UnauthorizedError) { // rate limit hit or invalid credentials }}Success resets the counter.
Configuration
Section titled “Configuration”The rate limiter is not currently configurable via AuthConfig. It is set to:
- Window: 60 seconds
- Max attempts: 5 per key
- Key:
login:${email}
For multi-instance deployments
Section titled “For multi-instance deployments”The built-in InMemoryRateLimiter is per-process. In a multi-instance setup,
rate limit state is not shared across instances. For production, you can wrap
the Auth.register / loginWithCredentials path with your own shared rate
limiter (Redis, etc.) before calling auth.login().
Best practices
Section titled “Best practices”- The built-in limiter is sufficient for single-process apps and development.
- For production multi-instance, add a Redis-backed limiter in front of
login. - Key on email (not IP) to avoid shared-IP lockouts.
Common mistakes
Section titled “Common mistakes”- Assuming the rate limiter spans multiple server processes (it doesn’t).
- Not handling
UnauthorizedErrorfromlogin()— the rate limit is a real auth error.
Related
Section titled “Related”- OAuth & Providers — credentials provider.
- Sessions — what happens after successful login.
