Deep dive 9 of the KubeCon Mumbai 2026 series, closing the security cluster on identity. Rishabh Singh (Principal Technical Support Engineer, Red Hat) demonstrated Keycloak 26.6's federated client authentication: instead of storing and distributing OAuth client secrets to hundreds of microservices, Keycloak trusts the workload identity your platform already issues — a Kubernetes service-account token or a SPIFFE JWT-SVID. The client authenticates with an ephemeral, platform-signed JWT; Keycloak validates it against the cluster's JWKS. Zero stored secrets, automatic rotation, one identity model.
This is the natural endpoint of the security cluster. DD07 made container root safe; DD08 made SBOMs verifiable yet private; this one removes the last big pile of long-lived secrets — the OAuth client secret — by federating trust to the platform itself.
Keycloak in one slide
Keycloak implements the foundational standards — OAuth 2.0, SAML, OpenID Connect — and acts as a centralized authentication server: SSO, user management, authorization, so developers don't write custom security code. In the CNCF world it's the centralized identity apps delegate to, the API security plane issuing access tokens for microservices, and the manager of complex flows like MFA and external identity federation.
Static secrets fail at scale
Both classic OAuth flows lean on a stored client_secret. In the authorization code flow (user login), the web app exchanges an authorization code plus its client secret for tokens. In the client credentials flow (an app acting on its own behalf), the app posts client_credentials and its client secret to get an access token. Either way, that secret is a long-lived bearer credential — and at cloud-native scale, that's the problem:
| Traditional client auth | Why it breaks |
|---|---|
| Client secrets stored persistently in Keycloak | a standing target |
| Distributed to every client instance (ConfigMaps) | secret sprawl across the fleet |
| Manual rotation across all deployments | high coordination risk |
| Static credential leakage | grants persistent access |
Federated client authentication — secretless clients
Keycloak 26.6 introduces federated client authentication: OIDC clients authenticate using ephemeral tokens, with native integration for Kubernetes and SPIFFE identities. Keycloak validates the platform identity, eliminating stored client secrets. The benefits map cleanly:
| Benefit | What it means |
|---|---|
| Zero secret management | completely eliminates storing client secrets. |
| Automatic rotation | token lifecycle is handled by the platform. |
| Enhanced security | credentials are short-lived and cryptographically signed. |
| Operational consistency | one identity model across all service meshes/clouds. |
The outcome, in the speaker's words: a unified identity plane, not a segregated secrets store.
Where it sits among Keycloak's auth methods
| Authenticator | How it works | Use case |
|---|---|---|
| Client ID & Secret | simple shared secret | legacy / non-containerized |
| Signed JWT | client signs its own JWT | clients that generate/rotate their own keys |
| Signed JWT — Federated | external IdP JWT validation | cloud-native (K8s SA, SPIFFE) |
| x509 Certificate | mutual TLS | older enterprise environments |
The new entry is "Signed JWT — Federated": starting in 26.6, Keycloak validates tokens issued by Kubernetes and SPIFFE rather than a key the client holds itself.
The shifting trust boundary
Fig 1 — Keycloak's trust boundary grows to accept JWTs from authoritative external issuers.
- Traditional trust: the boundary is defined by local client metadata and stored secrets.
- The federation: the boundary extends to authoritative external issuers — Kubernetes and SPIFFE.
- Keycloak's new role: it accepts external workload-identity tokens (JWTs) as proof of client identity.
- Outcome: delegating identity validation is what enables federated client authentication.
The setup — realm, IdP, and two clients
The demo used a dedicated kubernetes realm to isolate workload identities, an Identity Provider configured for Kubernetes OIDC, and — neatly — two clients for comparison: web-k8s-client (federated-jwt, authenticates with a K8s SA token) and web-secret-client (traditional secret).
It's a preview feature, enabled with:
KC_FEATURES="client-auth-federated,kubernetes-service-accounts"
Establishing trust with Kubernetes
Three steps, one command:
# 1. Create the Kubernetes Identity Provider kcadm.sh create identity-provider/instances -r kubernetes \ -s alias=kubernetes \ -s providerId=kubernetes \ -s config.issuer=https://kubernetes.default.svc.cluster.local # 2. Keycloak auto-fetches the JWKS from the issuer URL # 3. Validates signature + claims (iss, sub, aud, exp), maps to a client # by issuer + subject matching
Client configuration — before and after
Before — web-secret-client | After — web-k8s-client |
|---|---|
| Client Authenticator: Client Id and Secret | Client Authenticator: Signed JWT — Federated |
Client Secret: •••••••••••• (stored) | Identity provider: kubernetes |
| — rotate & distribute manually | Federated subject: system:serviceaccount:default:my-serviceaccount |
The application flow — a service-account JWT as client credential
On the Kubernetes side, the workload mounts a projected service-account token — short-lived, audience-scoped, auto-rotated:
serviceAccountName: demo-app
volumes:
- name: keycloak-token
projected:
sources:
- serviceAccountToken:
path: token
audience: https://keycloak/realms/k8s # cryptographically scoped
expirationSeconds: 3600 # ephemeral
Fig 2 — inject → audience-bind → send as client_assertion → Keycloak verifies. No secret anywhere.
Keycloak then validates in three checks:
- Signature check — verify the JWT signature against the Kubernetes JWKS endpoint.
- Audience match — the token's
audclaim must match the Keycloak realm issuer URL. - Client mapping — map the token's
sub(service-account identity) to the provisioned Keycloak client.
If all pass, the client is authenticated and Keycloak issues the access token. The client sends the SA JWT in the standard client_assertion parameter — so it's ordinary OIDC client authentication, just with a platform-issued assertion instead of a stored secret.
The core value
The summary was crisp. Problem: static client secrets require manual distribution and rotation. Solution: federated client authentication eliminates static secrets by trusting platform-issued workload identity tokens — a Kubernetes SA token or a SPIFFE JWT-SVID. The credential you were storing and rotating by hand is replaced by one the platform already issues, scopes, signs, and rotates for you.
FAQ
How is this different from a client signing its own JWT?
"Signed JWT" means the client holds its own key and signs assertions — you've still got a key to manage and rotate. "Signed JWT — Federated" delegates to an external issuer (Kubernetes/SPIFFE): the client presents a token the platform issued and signed, so there's no client-held key or secret at all.
What stops a stolen SA token from being replayed?
Audience scoping and short lifetime. The projected token's aud is bound to the Keycloak realm URL, so it's useless against any other service, and it expires (e.g. 3600s) and auto-rotates. Keycloak also checks signature, issuer, and subject before accepting it.
Does this work with SPIFFE too, or just Kubernetes?
Both. The feature federates to authoritative external issuers; the demo used Kubernetes OIDC, but SPIFFE JWT-SVIDs are a first-class target. The model is identical — validate a platform-issued workload JWT instead of a stored secret.
Is it production-ready?
In 26.6 it's a preview feature (enabled via KC_FEATURES). The pattern is sound and aligns with where the ecosystem is heading (workload identity over static secrets), but treat preview features with the usual caution and watch the Keycloak release notes for graduation.
Takeaways
- OAuth client secrets are the last big pile of long-lived credentials — stored, distributed, and rotated by hand at microservice scale.
- Keycloak 26.6 federates client auth to platform issuers, so clients authenticate with ephemeral, platform-signed JWTs.
- "Signed JWT — Federated" validates K8s service-account tokens and SPIFFE JWT-SVIDs against the issuer's JWKS.
- Audience binding + short expiry + auto-rotation make the credential narrowly scoped and self-expiring.
- The win is a unified identity plane — one model across meshes and clouds, not a segregated, leak-prone secrets store.
That closes the security cluster. Next in the series — Deep dive 10: Building & Orchestrating Production-Ready Agentic AI Systems, opening the AI/agents block.
References
- KubeCon Mumbai 2026 — Day 1 index · the rest of the series
- Keycloak — Federated Client Authentication · the reference docs
- Demo code (rishabhsvats/kubecon-2026) · the realm, IdP, and clients
- SPIFFE · K8s service-account tokens · the workload-identity sources