Files
homelab-frontend/tasks/3.1-jwks-fetch-and-rotation.md
T
Story Crater BotandClaude Opus 5 058f11cf2b
CI / Test (push) Canceled after 0s
CI / Vet (push) Canceled after 0s
CI / Build (push) Canceled after 0s
CI / Security (govulncheck) (push) Canceled after 0s
chore: initial commit of Go API gateway
Baseline for the Kong replacement on api.riotpiao.com. Brings the working
tree under version control for the first time: gateway source, the task
board that drives the agent runs, test fixtures, and K8s manifests.

Anchor the gateway ignore rule to the repo root. Unanchored, "gateway"
also matched the cmd/gateway/ source directory, so the program entrypoint
was excluded from every commit.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-08-19 20:54:34 -07:00

2.0 KiB

3.1 — JWKS fetch and rotation (GREEN)

Phase: 3 — Authentication Stage: GREEN Depends on: 0.2, 0.3

  • The signing key set is fetched from Authentik at https://authentik.riotpiao.com at runtime; no public key is pinned in configuration, in an image, or in a manifest
  • The JWKS URL is configuration, so a local stub issuer can be pointed at instead — no cluster and no credentials needed to verify this task
  • Fetched keys are cached and reused; a token verification does not trigger a network call per request
  • A token whose key id is not in the cache triggers a refetch, and the refetch is rate-limited so an unknown-key flood cannot hammer Authentik
  • After a key rotates at the issuer, tokens signed by the new key verify without restarting, redeploying, or editing configuration
  • Tokens signed by a key that is no longer published stop verifying once the cache reflects that
  • GET /readyz fails while JWKS has never been fetched successfully, and GET /healthz is unaffected
  • A JWKS fetch failure while a valid cache exists does not take the gateway down; it is logged and retried
  • No key material, token, or fetched secret appears in logs

This deletes the rotation runbook AUTH-PLAN.md was forced to propose. That runbook existed only because Kong OSS needed a pinned rsa_public_key; it must not be carried forward.

Verify

# stub issuer serving a JWKS, gateway pointed at it
curl -s -o /dev/null -w '%{http_code}\n' localhost:8080/readyz    # expected: 200 once JWKS has been fetched

# stub returns 500 for JWKS from a cold start
curl -s -o /dev/null -w '%{http_code}\n' localhost:8080/readyz    # expected: 503
curl -s -o /dev/null -w '%{http_code}\n' localhost:8080/healthz   # expected: 200

# rotate the stub's key, then present a token signed by the new key, no restart
curl -s -o /dev/null -w '%{http_code}\n' localhost:8080/v1/models -H "authorization: Bearer $NEW_TOKEN"
# expected: 200 — refetch happened on the unknown key id