Skip to content

Add abuse protection for Account password sign-in #3340

Description

@aofei

Problem

Account password sign-in currently verifies administrator-managed passwords through POST /account/session. The latest password policy work hardens password creation, hash format, and timing behavior for missing credentials, but wrong-password retries are still not throttled or cooled down explicitly.

Because password verification uses Argon2id, repeated sign-in attempts can amplify CPU and memory cost. Repeated attempts against a real account can also enable password guessing unless the sign-in boundary applies request throttling or failure-aware cooldown.

Current state

  • Managed password creation is restricted to printable ASCII, 8 to 128 bytes, with no leading or trailing spaces.
  • Password sign-in accepts the submitted password verbatim up to 128 bytes for existing credential compatibility.
  • Password verification uses the fixed Account Argon2id profile.
  • Unknown users and users without password credentials run dummy Argon2id verification before returning invalid sign-in.
  • There is no login-specific failed-attempt counter, cooldown, account lockout, 429, or Retry-After.
  • The existing Redis sliding-window limiter in internal/ratelimit may be reusable for simple request throttling.

Proposed scope

Add abuse protection to POST /account/session.

Initial scope should prefer lightweight Redis-backed throttling:

  • Limit by source IP.
  • Limit by username plus source IP.
  • Return 429 Too Many Requests with Retry-After when throttled.
  • Keep ordinary invalid credentials as 401 Unauthorized.
  • Avoid exposing whether the username exists or has a password credential.
  • Keep the protection compatible with hosted sign-in and Account Web callers.

Candidate behavior

  • Check throttling before password verification so denied bursts do not trigger unbounded Argon2id work.
  • Record attempts regardless of whether the username exists, so username enumeration does not get a cheaper path.
  • Treat username comparisons consistently with the existing sign-in path.
  • Clear or naturally expire attempt state through Redis TTLs rather than adding account-level persistent lock state.
  • Use conservative thresholds first, then tune from production signals if needed.

Acceptance criteria

  • Password sign-in attempts are throttled before unbounded Argon2id work can be triggered.
  • Throttled responses include Retry-After.
  • Invalid credentials remain indistinguishable across unknown user, missing password credential, and wrong password.
  • OpenAPI documents the new 429 response for POST /account/session.
  • Product docs describe password sign-in abuse protection at a high level.
  • Backend tests cover allowed, invalid, and throttled sign-in attempts.
  • Frontend Account Web behavior handles the throttled response without treating it as a generic credential failure if applicable.

Non-goals

  • CAPTCHA.
  • Device fingerprinting.
  • Risk scoring.
  • Permanent account lockout.
  • Administrator unlock workflow.
  • Self-service password reset.
  • Changing the managed password policy.
  • Changing the Argon2id profile.
  • Reworking third-party identity provider sign-in.

Notes

A failure-aware cooldown can be considered after the basic request throttle is in place. Username-only lockout should be avoided initially because it can let attackers lock other users out.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions