Skip to content

fix(middleware): stop rate-limiting auth page loads, cap only auth attempts#161

Merged
pratikbodkhe merged 1 commit into
mainfrom
fix/auth-page-rate-limit
Jul 7, 2026
Merged

fix(middleware): stop rate-limiting auth page loads, cap only auth attempts#161
pratikbodkhe merged 1 commit into
mainfrom
fix/auth-page-rate-limit

Conversation

@pratikbodkhe

Copy link
Copy Markdown
Contributor

Problem

staging.getminutia.com/signup intermittently served a bare Too Many Requests page. The middleware capped ALL requests to auth pages (/login, /signup, /accept-invite, /auth/callback, /reset-password) at 10/min per IP in production, and that budget was consumed by GET page loads, Next.js Link prefetches, and RSC requests, not just sign-in attempts. A user bouncing between login and signup trips it inside a minute and is locked out of the page for the rest of the window. Credential POSTs go straight to GoTrue from the browser client, so the old cap was in practice throttling only page views.

Fix

Split the budget by method in a new pure module src/lib/rate-limit.ts:

  • GET/HEAD page loads: separate auth-page bucket, 120/min prod (2000 dev), a ceiling a human cannot plausibly trip but that still slows scanners
  • Everything else (real auth attempts, server actions): keeps the strict 10/min prod auth-attempt bucket
  • Separate bucket keys, so a prefetch storm can never starve submissions
  • API limiter (100/min, bare-IP key) untouched

Tests

  • New contract verifier scripts/verify-rate-limit.test.mjs (pnpm test:rate-limit, wired into CI): every branch of authRateBudget and isRateLimited (window reset, key independence, bucket separation, prod/dev budgets)
  • Full local Playwright suite run in a clean worktree; failure set compared spec-by-spec against the parent commit: no regressions (persistent failures are the known local-env set, two flaky specs pass on rerun)

…tempts

The /login, /signup, /accept-invite, /auth/callback, and /reset-password
routes shared a 10 requests/min per-IP budget that counted GET page
loads, Next.js Link prefetches, and RSC requests alongside actual
sign-in attempts. A user bouncing between login and signup tripped it
within a minute and got a bare Too Many Requests page (seen on staging).

Split the budget by method: mutating requests (real auth attempts) keep
the strict 10/min production cap; GET/HEAD page loads get a separate
120/min bucket a human cannot plausibly trip but that still slows
scanners. Extracted the decision into src/lib/rate-limit.ts with a
contract verifier (pnpm test:rate-limit) wired into CI.
@pratikbodkhe pratikbodkhe merged commit abb2c06 into main Jul 7, 2026
34 of 36 checks passed
@pratikbodkhe pratikbodkhe deleted the fix/auth-page-rate-limit branch July 7, 2026 22:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant