Recipe
Recipe: JOSE / JWKS key rotation design
A stateless key-rotation pattern using JWKS endpoints, kid claims, and Ed25519 signing keys — no database required.
Ingredients
- Ed25519 keypair per rotation epoch
- JWKS endpoint serving active + next key
- kid claim in every JWT header
- Grace period for key overlap (72h default)
- Revocation list (kid → expiry) in Upstash KV
Flow
- Generate a new keypair; assign a kid with epoch timestamp.
- Publish the public key to /.well-known/jwks.json alongside the previous key.
- Sign all tokens with the active private key; include the kid in the JWT header.
- Verify by fetching JWKS, matching kid, and checking Ed25519 signature.
- Rotate after grace period; retire the old key and remove it from JWKS.
JWKS response
{
"keys": [
{
"kty": "OKP",
"crv": "Ed25519",
"kid": "2026-05-26T00",
"x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo",
"use": "sig"
}
]
}Edge cases
- Cache JWKS at edge for 60s; serve stale on origin failure.
- If kid is missing, reject with 401 — no fallback guessing.
- Revoked keys stay in KV for token lifetime + clock skew.
- Pre-generate next key 24h before rotation to warm caches.