A dependency-light OAuth2-style authentication service in FastAPI: hand-rolled HS256 JWTs (no pyjwt),
versioned signing keys with zero-downtime rotation, refresh-token reuse detection, and strict
cross-tenant object-level authorization.
Built to demonstrate the security patterns behind enterprise SSO fleets: kid-keyed verification,
hmac.compare_digest everywhere, PBKDF2 password hashing (stdlib only), denylisted refresh JTIs,
and security headers on every response.
Not for production use — for demonstrating depth. Every moving part (b64url encoding, kid lookup,
alg pinning, exp checking) is explicit and unit-tested. Swap jwt_util.sign/verify for pyjwt in one file
if you deploy it.
| Method | Path | Auth | Notes |
|---|---|---|---|
| POST | /token |
credentials | returns access (15 min) + refresh (12 h) pair |
| POST | /refresh |
refresh token | rotates pair; old JTI revoked (reuse = 401) |
| GET | /me |
access token | echoes subject, tenant, scopes |
| GET | /v1/tenants/{tenant_id}/profile |
access token | 403 on tenant mismatch |
| POST | /admin/rotate |
admin scope | new signing key; old tokens stay valid within retention window |
KeyStore keeps a bounded version window (max_versions). Rotation mints k2, k3, ...; verification
looks up by the token's kid header so previously issued tokens remain valid until they age out of the window —
the same pattern as JWKS-based rotation in production IdPs, minus the network.
pip install -r requirements.txt
uvicorn auth_gateway.app:app --reload
curl -X POST localhost:8000/token -d '{"username": "alice", "password": "wonderland"}' -H "Content-Type: application/json"
curl localhost:8000/me -H "Authorization: Bearer <access_token>"pytest -q # 15 tests: jwt roundtrip/tamper/expiry/kid, rotation windows, reuse detection, cross-tenant 403s, headersMIT