Kubernetes OIDC Integration: How We Mastered K8s Authentication with Keycloak in Gardener KaaS
As we learned in our previous article, authentication plays a crucial role in securing modern cloud-native environments and managing it efficiently is critical, especially in complex, multi-cluster environments. OpenID Connect (OIDC) is widely adopted as the standard for integrating Identity Providers (IdPs) with Kubernetes and Keycloak, an open-source identity and access management solution, is a top choice for implementing OIDC.
A couple of months ago, our DevOps team had to tackle the challenge of integrating OpenID Connect (OIDC) via Keycloak for Gardener’s Kubernetes-as-a-Service (KaaS) setup. Our team delivered yet another C12N private cloud installation designed for distributed IoT applications and as a part of C12N we integrate Gardener KaaS.
However, this time the primary users were development teams working on multiple projects simultaneously, which requires not only tenant and network isolation, but also managed Kubernetes service, and centralized, secure access management. This is where we decided to integrate Keycloak in order to centralize authentication and authorization for Kubernetes.
This was not one of our usual implementations and with little to none documentation and examples on Gardener OIDC integration, we were confronted with multiple hurdles that we had to overcome before being able to achieve seamless integration.
Since Gardener CP components are integrated with and extend the Kubernetes API, its web interface (Gardener Dashboard) supports the same authentication mechanisms as Kubernetes itself. This makes it possible to leverage OIDC to provide secure, token-based authentication.
In this article, we will give you a glimpse of how our team managed to set up Authentication with an Identity provider (OIDC) via Keycloak.
Prerequisites
Before diving into the configuration, ensure the following are in place:
- Keycloak Installed and Accessible: Keycloak should be up and running, reachable at a defined URL.
- Gardener Dashboard Deployed: Ensure the Gardener dashboard is running in the same Kubernetes cluster as its control plane. (it is possible to run Gardener dashboard in any other place. But it would be simpler to do so in the same cluster)
- Kubernetes Cluster Access: Administrative access to the Kubernetes cluster where Gardener is deployed.
- SSL Certificates: Ensure the Kubernetes API server can securely communicate with Keycloak.
Configuration
Validating Tokens for the Gardener Dashboard
To enable OIDC login for the Gardener dashboard, the tokens issued by Keycloak to access the Gardener dashboard must be validated by the Kubernetes API, as suggested in the documentation. There are two ways to achieve this:
- Separate OIDC Clients:
Create separate OIDC clients in Keycloak for the Gardener dashboard and Kubernetes API, configuring audience mappers to return valid client_id values for both. - Single OIDC Client (Preferred Method):
Use the same OIDC client for both the Gardener dashboard and Kubernetes API. This is the simpler approach, especially since Gardener’s dashboard is deployed in the same cluster as other control plane components. We chose this method for its simplicity and efficiency.
Now let’s explore step by step how to configure Keycloak to act as an OIDC provider for a Kubernetes-based environment like Gardener:
1. Keycloak Setup
Create a Client Realm:
Keycloak ships with an “admin” realm by default. It’s best practice to create a new realm for client authentication, ensuring separation of concerns.
- Navigate to the Keycloak admin console.
- Create a new realm named client or a similar meaningful name.
Create the Kubernetes Client:
Once the realm is created, set up a Keycloak client for Kubernetes. Kubernetes API can use CA to validate OIDC client trust, but we need client password for Gardener dashboard
- Go to Clients in the new realm and click Create.
- Set the client ID to kubernetes, enable OIDC, and set the client protocol to openid-connect.
- Ensure the client is set to confidential to generate a client secret.


Configure Required Scopes:
Add the necessary scopes under the Client Scopes tab to avoid authentication errors:
openid
email
profile
groups
audience:server:client_id:gardener
Audience:server:client_id:kube-kubectl

These scopes are required by Gardener dashboard, if you don’t add them the Dashboard will show you the following error when you try to login:
Login Error
invalid_scope (Invalid scopes: openid email profile groups audience:server:client_id:gardener audience:server:client_id:kube-kubectl)
2. Kubernetes API Server Configuration
Kubernetes integration is straightforward. Modify the kube-apiserver.yaml manifest located at /etc/kubernetes/manifests and append the following configurations:
- --oidc-issuer-url=https://keycloak.example.com/realms/<REALM_NAME>
- --oidc-client-id=kubernetes
- --oidc-username-claim=preferred_username
- --oidc-groups-claim=groups
- '--oidc-username-prefix=oidc:'
- '--oidc-groups-prefix=oidc:'
- --oidc-ca-file=/etc/kubernetes/ssl/keycloak.crt
Optionally restart kubelet to speed up the rollout of these changes.
3. Setting Up Group Permissions
To grant Keycloak users access to Kubernetes resources, create a Kubernetes group that matches the Keycloak group:
Lets create a sample group k8s-cluster-admin

A binding with the same group name must be configured in Kubernetes
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: oidc-cluster-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: oidc:k8s-cluster-admin
namespace: default
Note: Ensure the group name includes the oidc: prefix to match the kube-apiserver.yaml configuration.
4. Configure Gardener
To configure Gardener we will use the same OIDC client as for Kubernetes cluster.
Dashboard
We install Gardener dashboard via Helm chart and install it in the same cluster as Gardener API.
Here are corresponding values for OIDC integration
Where:
- KEYCOAK_REALM – is the name of realm created in 1st step
- KEYCLOAK_CLIENT_SECRET – name of Keycloak Kubernetes client created in 1st step
- garden.example.com – Web URL via which Gardener Dashboard is exposed (e.g. K8s Ingress)
global:
dashboard:
oidc:
# well-known URL for OpenID Provider Issuer Discovery
issuerUrl: https://keycloak.example.com/realms/><KEYCOAK_REALM>
clientId: gardener
clientSecret: "<KEYCLOAK_CLIENT_SECRET>"
redirectUris:
- <https://garden.example.com/oidc>
- <https://garden.example.com/auth/callback>
- <https://garden.example.com/callback>
- <https://garden.example.com>
5. Logging into the Gardener Dashboard
With everything set up, navigate to the Gardener Dashboard UI, select the OIDC tab, and log in using the Keycloak credentials. If all configurations are correct, you should successfully authenticate and access the dashboard.

Closing Thoughts
Setting up OIDC with Keycloak for Gardener was a technical challenge that pushed us towards problem-solving and innovation. While the process was intricate and documentation was scarce, we managed to complete the implementation successfully and gain experience along the way.
If your organization is looking to centralize Kubernetes authentication and authorization, Cloudification’s DevOps team is here to help. Contact us to unlock secure, streamlined authentication for your Kubernetes clusters today!