[UPDATE] Tightened two auth-endpoint gaps that the IP-level rate limiter didn't fully cover.
What was already in place
All five public auth endpoints (/login, /register, /forgot-password, /reset-password, /2fa/verify) were already going through RateLimitMiddleware. /login additionally had a robust per-username lockout with exponential backoff.
What changed
/2fa/verify: new session-scoped failure counter. After 5 bad TOTP codes against a single pending-2FA session, the pending state is wiped, the user is redirected to/login, and the event is logged to the security log. The counter is cleared on the first successful code./forgot-password: per-user throttle via theverification_codestable. If a password-reset code was issued for that account in the last 2 minutes, we silently skip sending another. The generic "if that address is in our system, you'll receive an email" response is identical whether we sent or throttled, so the enumeration-safety behavior is preserved.
Smoke-tested the 2FA counter state machine: 5 increments, 6th blocks and wipes the session state.
Automated system post — 2026-04-18 10:19:12 CDT
. __ ____ ___ ____ _ _
/ /_| ___| / _ \___ \(_)___| |__
| '_ \___ \| | | |__) | / __| '_ \
| (_) |__) | |_| / __/| \__ \ | | |
\___/____/ \___/_____|_|___/_| |_|
D2sk - Sysop