# Quickstart: Login Brute-Force Protection ## Prerequisites - API running (via `docker compose up` or locally with `.env` set) - `curl` available --- ## Scenario 1: Trigger the rate limiter Send 6 consecutive failed login attempts (default threshold is 5): ```bash for i in $(seq 1 6); do echo "Attempt $i:" curl -s -o /dev/null -w "%{http_code}\n" \ -X POST http://localhost:8000/api/v1/auth/token \ -H "Content-Type: application/json" \ -d '{"username": "wrong", "password": "wrong"}' done ``` Expected output: ``` Attempt 1: 401 Attempt 2: 401 Attempt 3: 401 Attempt 4: 401 Attempt 5: 401 Attempt 6: 429 ``` The 6th attempt returns 429. Inspect the headers: ```bash curl -i -X POST http://localhost:8000/api/v1/auth/token \ -H "Content-Type: application/json" \ -d '{"username": "wrong", "password": "wrong"}' ``` Expected headers include: ``` HTTP/1.1 429 Too Many Requests Retry-After: 900 ``` Expected body: ```json {"detail": "Too many failed login attempts. Please try again later.", "code": "login_rate_limited"} ``` --- ## Scenario 2: Successful login resets the counter Make some failed attempts, then log in with valid credentials: ```bash # Fail twice for i in 1 2; do curl -s -o /dev/null -w "fail $i: %{http_code}\n" \ -X POST http://localhost:8000/api/v1/auth/token \ -H "Content-Type: application/json" \ -d '{"username": "wrong", "password": "wrong"}' done # Succeed — resets counter curl -s -o /dev/null -w "success: %{http_code}\n" \ -X POST http://localhost:8000/api/v1/auth/token \ -H "Content-Type: application/json" \ -d '{"username": "'"$OWNER_USERNAME"'", "password": "'"$OWNER_PASSWORD"'"}' # Now fail 5 more times — counter was reset, so no 429 yet for i in $(seq 1 5); do curl -s -o /dev/null -w "fail after reset $i: %{http_code}\n" \ -X POST http://localhost:8000/api/v1/auth/token \ -H "Content-Type: application/json" \ -d '{"username": "wrong", "password": "wrong"}' done ``` Expected: all "fail after reset" lines return 401 (not 429), confirming the counter was reset. --- ## Scenario 3: Observe log output While triggering the rate limiter (Scenario 1), watch API logs: ```bash docker compose logs -f api ``` After the threshold is crossed you should see a line like: ``` WARNING app.auth.rate_limiter:rate_limiter.py:NN Login blocked for 172.18.0.1 after 5 failures ``` --- ## Environment variable overrides To test with a lower threshold without code changes: ```bash LOGIN_MAX_FAILURES=2 LOGIN_WINDOW_SECONDS=60 LOGIN_COOLDOWN_SECONDS=30 \ uvicorn app.main:app --reload ``` Then only 2 failures trigger the lockout, and it clears after 30 seconds.