python 45 lines · 8 steps

API key authentication as a FastAPI dependency

A reusable dependency extracts, verifies, and validates an API key so route handlers receive an already-authenticated client.

Explained by highlit
1import secrets
2 
3from fastapi import Depends, FastAPI, HTTPException, Security, status
4from fastapi.security import APIKeyHeader
5 
6from app.config import settings
7from app.db import Database, get_db
8from app.models import ApiClient
9 
10api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)
11 
12 
13async def get_api_client(
14 api_key: str | None = Security(api_key_header),
15 db: Database = Depends(get_db),
16) -> ApiClient:
17 if not api_key:
18 raise HTTPException(
19 status_code=status.HTTP_401_UNAUTHORIZED,
20 detail="Missing API key",
21 headers={"WWW-Authenticate": "Header"},
22 )
23 
24 client = await db.api_clients.find_by_key_prefix(api_key[:8])
25 if client is None or not secrets.compare_digest(client.api_key, api_key):
26 raise HTTPException(
27 status_code=status.HTTP_403_FORBIDDEN,
28 detail="Invalid API key",
29 )
30 
31 if client.revoked_at is not None:
32 raise HTTPException(
33 status_code=status.HTTP_403_FORBIDDEN,
34 detail="API key has been revoked",
35 )
36 
37 return client
38 
39 
40app = FastAPI()
41 
42 
43@app.get("/v1/usage")
44async def read_usage(client: ApiClient = Depends(get_api_client)):
45 return {"client_id": client.id, "plan": client.plan, "quota": client.quota_remaining}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Modeling auth as a dependency keeps route handlers focused on business logic while centralizing security checks.
  2. 2Use secrets.compare_digest for secret comparison to avoid leaking information through timing side channels.
  3. 3Distinguish 401 (no credentials) from 403 (bad or revoked credentials) so clients get accurate feedback.

Related explainers

Share this explainer

Here's the card — post it anywhere.

API key authentication as a FastAPI dependency — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code