Files
reactbin/specs/009-login-rate-limiting/contracts/auth.md
agatha 7a835d3172 Feat: Rate-limit login endpoint to block brute-force attacks
After LOGIN_MAX_FAILURES consecutive failed attempts from the same source
IP within LOGIN_WINDOW_SECONDS, POST /api/v1/auth/token returns HTTP 429
with a Retry-After header for LOGIN_COOLDOWN_SECONDS. A successful login
resets the counter. Trusted upstream proxy IPs/CIDRs can be declared via
LOGIN_TRUSTED_PROXY_IPS so X-Forwarded-For is honoured correctly behind
nginx ingress or similar reverse proxies.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 21:01:37 +00:00

1.8 KiB

API Contract: Authentication

POST /api/v1/auth/token

Authenticates the owner and returns a JWT access token.

This endpoint is modified by feature 009 to enforce brute-force protection. All previous behaviour is preserved. One new response code (429) is added.

Request

POST /api/v1/auth/token
Content-Type: application/json
{
  "username": "string",
  "password": "string"
}

Responses

200 OK — Credentials accepted

{
  "access_token": "<jwt>",
  "token_type": "bearer",
  "expires_in": 86400
}

Side effect: resets the failure counter for the caller's IP address.


401 Unauthorized — Credentials rejected

{
  "detail": "Invalid credentials",
  "code": "invalid_credentials"
}

Side effect: increments the failure counter for the caller's IP address. If the counter reaches LOGIN_MAX_FAILURES, subsequent requests from this IP will receive 429 until the cooldown expires.


429 Too Many Requests — Source blocked after repeated failures

This response is new in feature 009.

HTTP/1.1 429 Too Many Requests
Retry-After: 900
Content-Type: application/json
{
  "detail": "Too many failed login attempts. Please try again later.",
  "code": "login_rate_limited"
}

The Retry-After header value is the configured cooldown duration in seconds (default: 900). It reflects the maximum possible wait, not the exact remaining lockout time.

No credentials are verified when this response is returned — the request is rejected before authentication is attempted.


Notes

  • The failure counter is per source IP address (TCP peer, not forwarded headers).
  • Threshold values (LOGIN_MAX_FAILURES, LOGIN_WINDOW_SECONDS, LOGIN_COOLDOWN_SECONDS) are not disclosed in any response.
  • Counters are in-memory and reset on process restart.