OIDC / JWKS Rotation Runbook¶
The inference gateway can validate OIDC bearer tokens beside API-key auth. Validation is
JWKS-driven: the gateway fetches signing keys from JWT_JWKS_URL, caches them for
JWT_CACHE_SECONDS, and verifies HS256, RS256, or ES256 signatures plus exp, nbf,
iss, aud, and required-scope claims. Because keys are fetched by kid, the gateway
follows standard JWKS key rotation without a redeploy.
Use this runbook to enable JWT auth and to drill issuer key rotation.
Enable JWT Validation¶
Set the JWT block in the gateway chart values and apply through GitOps. Configuration maps to
auth.jwt.* in deploy/charts/inference-gateway/values.yaml.
auth:
enabled: true # API-key auth stays available alongside JWT
jwt:
enabled: true
jwksUrl: "https://<issuer>/.well-known/jwks.json"
issuer: "https://<issuer>/"
audience: "private-ai-platform-kit"
requiredScopes:
- inference.invoke
cacheSeconds: 300
IdP-specific endpoints¶
| IdP | issuer |
jwksUrl |
|---|---|---|
| Keycloak | https://<host>/realms/<realm> |
https://<host>/realms/<realm>/protocol/openid-connect/certs |
| Auth0 | https://<tenant>.auth0.com/ |
https://<tenant>.auth0.com/.well-known/jwks.json |
| Okta | https://<org>.okta.com/oauth2/<authz-server> |
https://<org>.okta.com/oauth2/<authz-server>/v1/keys |
| Microsoft Entra ID | https://login.microsoftonline.com/<tenant>/v2.0 |
https://login.microsoftonline.com/<tenant>/discovery/v2.0/keys |
Resolve issuer and jwksUrl from the IdP discovery document at
https://<issuer>/.well-known/openid-configuration (the issuer and jwks_uri fields).
Rotation Drill¶
Goal: prove the gateway accepts tokens signed with a newly rotated key without downtime, and stops accepting retired keys.
- Publish the new key. Add the new signing key to the IdP so the JWKS document serves both
the current key (
kid-old) and the new key (kid-new). Do not retire the old key yet. - Wait for cache expiry. The gateway refreshes its JWKS cache after at most
JWT_CACHE_SECONDS. New gateway pods refresh on first authenticated request. - Verify new-key acceptance. Mint a token signed with
kid-newand confirm aPOST /v1/chat/completionscall returns a non-401 status: - Confirm old-key tokens still validate until they expire, so in-flight sessions are not broken during the overlap window.
- Retire the old key. Once all
kid-oldtokens have expired (after theirexp), removekid-oldfrom the IdP. After the next cache refresh the gateway rejects any token still presentingkid-oldwith401and reasoninvalid_or_missing_api_key. - Record evidence. Capture the HTTP codes from steps 3-5 and the
inference_gateway_auth_failures_totalmetric delta for the drill window.
Rollback¶
If new-key tokens are rejected after the cache window, re-add kid-old to the JWKS document
(reverting step 5) so existing tokens validate, then investigate the new key's kid, alg,
and use fields. Lowering JWT_CACHE_SECONDS shortens the propagation window for the next
attempt. Tightening issuer, audience, or requiredScopes only affects claim validation,
not key selection.
Validation¶
Key selection, signature verification, claim validation, and rotation behavior are covered by
src/inference-gateway/tests/test_jwt_auth.py, including the rotated-key case where a
retired kid is rejected while the active kid validates.