Problem
Rate limiting is currently applied uniformly at 20 requests/minute per IP across all endpoints. Authentication-sensitive endpoints like `/oauth/login`, `/oauth/register`, `/oauth/forgot-password`, and `/oauth/reset-password` are prime targets for brute-force and credential stuffing attacks but receive the same generous limit as read-only endpoints like `/health` and `/.well-known/jwks.json`.
Why it matters
- At 20 req/min, an attacker can try 20 passwords per minute (28,800/day) against a single account with no lockout
- Password reset and registration endpoints are similarly exposed
- The in-memory rate limiter resets on server restart, providing no persistent protection
Suggested approach
- Tighter limits on auth endpoints: e.g. 5 req/min on `/oauth/login`, `/oauth/forgot-password`, `/oauth/reset-password`, `/oauth/register`
- Account-based rate limiting: After N failed login attempts for a given username (e.g. 10), temporarily lock the account or require a CAPTCHA, regardless of source IP
- Consider whether persistent rate limiting (e.g. Redis-backed) is worth the added complexity for the project's scale
Even just step 1 (a second rate limiter middleware with a lower threshold applied to auth routes) would meaningfully improve the security posture.
Problem
Rate limiting is currently applied uniformly at 20 requests/minute per IP across all endpoints. Authentication-sensitive endpoints like `/oauth/login`, `/oauth/register`, `/oauth/forgot-password`, and `/oauth/reset-password` are prime targets for brute-force and credential stuffing attacks but receive the same generous limit as read-only endpoints like `/health` and `/.well-known/jwks.json`.
Why it matters
Suggested approach
Even just step 1 (a second rate limiter middleware with a lower threshold applied to auth routes) would meaningfully improve the security posture.