Rotate IdP Client Secrets and JWKS
What this covers
- IdP client credentials used by the BFF (client_id/client_secret for token and introspection calls)
- BFF signing key and JWKS for private_key_jwt (if used)
- Other BFF secrets:
TOKEN_HASH_SALT,UA_HASH_SALT,CSRF_SECRET_KEY,STATE_TOKEN_KEY
Where secrets live (compose default)
- Docker secrets under
/run/secrets(seeCRUDService/docker-compose-authzen4.yml) and env vars for non-secrets. - BFF reads:
AUTH_CLIENT_ID,AUTH_CLIENT_SECRETfor IdP callsTOKEN_HASH_SALT(required at startup) andUA_HASH_SALTCSRF_SECRET_KEY,STATE_TOKEN_KEYBFF_JWT_SIGNING_KEYor key material inBFF_KEYS_DIRfor JWKS
Rotate IdP client secrets
- Create a new secret material in your secrets store and update your compose/K8s secrets:
- Docker secret
oidc-client-secretor envAUTH_CLIENT_SECRET
- Docker secret
- Deploy the BFF with both old and new credentials valid at the IdP.
- Verify bearer introspection and code‑flow token exchange still succeed.
Rotate BFF signing key (JWKS)
- Code paths:
ms_bff_spike/ms_bff/src/routes/jwks.py,ms_bff_spike/ms_bff/src/crypto/jwks_manager.py,ms_bff_spike/ms_bff/scripts/rotate_keys.py. - By default, the BFF ensures a key exists under
BFF_KEYS_DIRand serves JWKS at/.well-known/jwks.json. - Recommended: configure the IdP client to use
jwks_uri: https://<your-bff-host>/.well-known/jwks.jsonso the IdP fetches keys automatically.
Manual rotation procedure
# In the BFF container or sidecar with the same volume mount
export BFF_KEYS_DIR=/app/keys
export AUTO_KEY_ROTATION=1
python -m ms_bff.scripts.rotate_keys
# In most setups no DCR call is required when using jwks_uri; the IdP will fetch new keys.
# If your IdP does not poll jwks_uri, consult IdP docs for a cache-bust endpoint.
Zero‑downtime tips
- Serve both old and new keys in JWKS during the grace window (jwks_manager preserves previous entries when you write the new JWKS).
- Keep old client credentials valid at IdP until all pods/instances are rolled.
- Stagger restarts; validate
/auth/login,/auth/callback, and bearer calls.
FAQ
- Why not rotate
client_secretautomatically?- Shared secrets are weaker and harder to distribute/rotate safely. Prefer
private_key_jwtwithjwks_uriso rotation is done by updating JWKS.
- Shared secrets are weaker and harder to distribute/rotate safely. Prefer
- Can I update
client_secretvia DCR PATCH?- Not via the public endpoint in our IdP. Use an admin/out-of-band update if absolutely necessary.
Rotate salts and CSRF/state secrets
TOKEN_HASH_SALT: restart required; BFF refuses startup if missing. Rotate during a maintenance window.UA_HASH_SALT: safe to rotate with restart; affects analytics hashing only.CSRF_SECRET_KEY: rotate with coordinated SPA downtime as existing CSRF tokens will be invalidated.STATE_TOKEN_KEY: rotate with caution; affects in‑flight login state.
Verification checklist
- After rotation, test:
- SPA login/callback flow and subsequent
/api/**calls (session) - Bearer flow to an
auth: bearerroute (introspection) - JWKS endpoint responds and IdP accepts private_key_jwt if enabled
- SPA login/callback flow and subsequent
References
- How‑to → Configure IdPs (idps.yaml)
- How‑to → Configure PDP (pdp.yaml)
- Reference → Observability (monitor auth errors during rotation)