← Docs
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

  1. Generate a new keypair; assign a kid with epoch timestamp.
  2. Publish the public key to /.well-known/jwks.json alongside the previous key.
  3. Sign all tokens with the active private key; include the kid in the JWT header.
  4. Verify by fetching JWKS, matching kid, and checking Ed25519 signature.
  5. 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.