Skip to content

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.

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.

The rate limiter is not currently configurable via AuthConfig. It is set to:

  • Window: 60 seconds
  • Max attempts: 5 per key
  • Key: login:${email}

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().

  • 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.
  • Assuming the rate limiter spans multiple server processes (it doesn’t).
  • Not handling UnauthorizedError from login() — the rate limit is a real auth error.