Sign in with GitHub By signing in you agree to the privacy policy.

track /05-keycloak-delegated-auth

Stop Writing Auth: Delegate to Keycloak

sign in to track your progress

Hand identity to an OIDC provider and defend the boundary that is left: validating tokens you did not issue, and surviving a key rotation.

Intermediate ~8h keycloakfastapidocker
keycloak-delegated-auth / spec.md v1.0

Context

Your API has hand-rolled auth: a users table, a password hash, a token you sign yourself. It works, and it is a liability — password reset, MFA, lockout and session revocation are all still yours to build.

Put Keycloak in front of it. The service stops issuing identity and starts verifying it, which is a smaller job with sharper edges: a token you did not sign, signed by a key that can change under you, carrying claims you have to decide whether to trust.

Run Keycloak in Compose, protect the API, and then attack it.

Requirements

What must be true — the how is yours.

  1. R1 Protected endpoints accept only tokens issued by your realm, with the signature verified against the provider's keys.
  2. R2 Authorization is enforced from claims: a valid token without the required role is refused. rehearsed by D3
  3. R3 An expired or tampered token is refused with a 401, never a 500 and never a stack trace. rehearsed by D1 · D2
  4. R4 The service survives a realm key rotation without a restart and without a window of blanket rejection. rehearsed by D4

Technical guidance

  • Fetch the signing keys from the provider's JWKS endpoint; never paste a key.
  • Validate issuer, audience and expiry — a valid signature alone proves little.
  • Cache JWKS or you make a network call per request; cache it wrong and a rotation locks everybody out.

Definition of done

All of them, or it isn't shipped.

  • 401, a log line, and no stack trace in the response. — not recorded yet D1
  • 401 for the expired token, and a freshly issued one still works immediately. — not recorded yet D2
  • 403, not 401 — authenticated, not authorised, and the log says which. — not recorded yet D3
  • The service fetches the new key and accepts the token without a restart; tokens still valid under the old key keep working until they expire. — not recorded yet D4
  • docker compose up brings the realm and the API up together, with the realm imported rather than clicked in by hand. — not recorded yet

nothing recorded yet — running the drills fills these in

spec v1.0 · drafted with AI, human-reviewed

Solutions

No solutions published yet. Complete the challenge and yours opens the thread.