Skip to content

feat(security): make auth-flow user scope independently enforceable (#506)#522

Merged
ericfitz merged 1 commit into
mainfrom
fix/506-user-scope-rate-limit
Jul 4, 2026
Merged

feat(security): make auth-flow user scope independently enforceable (#506)#522
ericfitz merged 1 commit into
mainfrom
fix/506-user-scope-rate-limit

Conversation

@ericfitz

@ericfitz ericfitz commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Summary

Closes #506.

The multi-scope auth-flow rate limiter (api/auth_flow_rate_limiter.go) enforced session, IP, and user scopes at the same 100/60s limit and checked them session → IP → user. Because single-IP traffic accumulates the IP counter at least as fast as the user counter, the IP scope (checked first, at an equal limit) always tripped first — so the user scope could never be the attributed blocker for real single-IP traffic. It was effectively subsumed by the IP scope.

Change (issue options 1 + 2)

  • Differentiate the limits — per-user limit is now 50/60s, half the per-IP limit (100/60s). The user scope now bites independently for single-account attacks (password-spray / account enumeration against one victim) from a single source IP.
    • Chose to lower the user limit rather than raise the IP limit (the issue's example): it is strictly more restrictive and can't lock out legitimate traffic — an interactive OAuth flow is a handful of requests, a client-credentials client with a 1h token needs ~1 request/hour, and ResetUserRateLimit clears the counter on successful login.
  • Reorder to most-specific-first (session → user → IP) so the user scope is correctly attributed when it bites.
  • Extract the three limits into named constants (authFlowSessionLimit, authFlowUserLimit, authFlowDefaultIPLimit).

Tests

  • New regression test: a single account from a single IP is blocked by the user scope at 50, not subsumed by the IP scope at 100.
  • Updated the user-scope unit tests and the TestAuthFlowRateLimiting_MultiScope integration sub-test to the new per-user limit.
  • make lint, make build-server, make test-unit (2381 passed) all green.
  • security-regression scan: PASS. security-review: no findings (change is strictly more restrictive; no new attack surface).

🤖 Generated with Claude Code

https://claude.ai/code/session_01Kk9GxWS9EpazjbwBKfMpUX

…506)

The multi-scope auth-flow rate limiter enforced session, IP, and user
scopes at the same 100/60s limit and checked them session -> IP -> user.
Because single-IP traffic accumulates the IP counter at least as fast as
the user counter, the IP scope (checked first, equal limit) always tripped
first and the user scope could never be the attributed blocker for real
single-IP traffic -- it was effectively subsumed by the IP scope.

Adopt options 1 + 2 from the issue:

- Differentiate the limits: per-user limit is now 50/60s, half the per-IP
  limit (100/60s), so the user scope bites independently for single-account
  attacks (password-spray / account enumeration against one victim) from a
  single source IP. Lowering the user limit (rather than raising the IP
  limit) is strictly more restrictive and cannot lock out legitimate
  traffic: an interactive OAuth flow is a handful of requests, a
  client-credentials client with a 1h token needs ~1 request/hour, and
  ResetUserRateLimit clears the counter on a successful login.
- Reorder to most-specific-first (session -> user -> IP) so the user scope
  is correctly attributed when it bites.

Extracts the three limits into named constants and adds a regression test
proving a single account from a single IP is blocked by the user scope at
50, not subsumed by the IP scope at 100. Unit and integration tests updated
to the new per-user limit.

Closes #506

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kk9GxWS9EpazjbwBKfMpUX
@ericfitz ericfitz merged commit e65e22e into main Jul 4, 2026
12 checks passed
@ericfitz ericfitz deleted the fix/506-user-scope-rate-limit branch July 4, 2026 18:23
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.

feat(security): make the auth-flow user scope independently enforceable (currently subsumed by IP scope)

1 participant