FastAPI: From Basics to Production · Authentication and Security

API Keys, Rate Limiting and Security Headers

Protect machine clients and public endpoints.

For machine-to-machine access, issue API keys: generate random keys, show them once, store only a hash, support multiple keys per client and revocation. Read them with APIKeyHeader. Add rate limiting per key/user/IP (gateway, Redis-based middleware, or libraries like slowapi), and set security headers at the proxy or in middleware.

import hashlib, secrets
from fastapi.security import APIKeyHeader

api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)


def new_api_key() -> tuple[str, str]:
    raw = "gr_" + secrets.token_urlsafe(32)
    return raw, hashlib.sha256(raw.encode()).hexdigest()      # show raw once, store hash


async def get_api_client(key: Annotated[str | None, Depends(api_key_header)], db: DB) -> ApiClient:
    if not key:
        raise HTTPException(401, "Missing API key")
    client = await api_clients.by_hash(db, hashlib.sha256(key.encode()).hexdigest())
    if client is None or client.revoked:
        raise HTTPException(401, "Invalid API key")
    if not await rate_limiter.allow(f"api:{client.id}", limit=1000, window_s=60):
        raise HTTPException(429, "Rate limit exceeded", headers={"Retry-After": "60"})
    return client

Common pitfalls

  • Storing API keys in plaintext.
  • Keys in query strings (they end up in logs).
  • No per-client limits, so one client can starve others.

Key points

  • Random keys, stored hashed
  • Header-based, revocable
  • Per-client rate limits with 429 + Retry-After

Further reading: FastAPI: APIKeyHeader

Practice questions

Why is a fast hash like SHA-256 acceptable for API keys but not passwords?

Answer

API keys are long random secrets with high entropy, so brute-forcing them is infeasible even with fast hashes; passwords are low-entropy and need slow hashing.

Why shouldn't API keys be sent in query parameters?

Answer

URLs are logged by proxies, servers and browsers and may leak via Referer headers.

Open in the app to mark lessons complete, take notes and track your progress.