OIDC Authentication for Kubernetes
Configure OpenID Connect (OIDC) authentication to integrate Kubernetes with identity providers like Keycloak, Okta, Azure AD, and Google for secure user access
Problem
Managing individual user certificates for Kubernetes access doesn’t scale and makes it difficult to implement single sign-on (SSO), enforce password policies, or integrate with corporate identity systems. You need centralized authentication with your existing identity provider.
Solution
Configure Kubernetes API server to use OpenID Connect (OIDC) for authentication, allowing users to authenticate using their corporate credentials through identity providers like Keycloak, Okta, Azure AD, or Google.
Architecture
sequenceDiagram
participant U as User / kubectl
participant IDP as Identity Provider (OIDC)<br/>Keycloak / Okta / Azure AD
participant K as kubectl
participant API as Kubernetes API Server
U->>IDP: 1. Request token
IDP->>K: 2. ID Token (JWT)
Note over K: Stores token in kubeconfig
K->>API: 3. API request + token
Note over API: 4. Validate token signature & claims<br/>5. Extract user identity & groups<br/>6. RBAC authorizationStep 1: Configure Identity Provider (Keycloak Example)
Create OIDC client in Keycloak:
# Create realm for Kubernetes
curl -X POST "https://keycloak.example.com/admin/realms" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"realm": "kubernetes",
"enabled": true,
"sslRequired": "external"
}'Create OIDC client configuration:
{
"clientId": "kubernetes",
"name": "Kubernetes API",
"enabled": true,
"publicClient": false,
"secret": "kubernetes-client-secret",
"redirectUris": [
"http://localhost:8000",
"http://localhost:18000"
],
"webOrigins": ["*"],
"protocol": "openid-connect",
"standardFlowEnabled": true,
"directAccessGrantsEnabled": true,
"attributes": {
"access.token.lifespan": "3600",
"pkce.code.challenge.method": "S256"
}
}Configure group mapper for Kubernetes:
{
"name": "groups",
"protocol": "openid-connect",
"protocolMapper": "oidc-group-membership-mapper",
"consentRequired": false,
"config": {
"full.path": "false",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "groups",
"userinfo.token.claim": "true"
}
}Step 2: Configure API Server for OIDC
Update kube-apiserver configuration:
# /etc/kubernetes/manifests/kube-apiserver.yaml
apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
namespace: kube-system
spec:
containers:
- name: kube-apiserver
command:
- kube-apiserver
# ... other flags ...
# OIDC Configuration
- --oidc-issuer-url=https://keycloak.example.com/realms/kubernetes
- --oidc-client-id=kubernetes
- --oidc-username-claim=preferred_username
- --oidc-username-prefix=oidc:
- --oidc-groups-claim=groups
- --oidc-groups-prefix=oidc:
- --oidc-ca-file=/etc/kubernetes/pki/oidc-ca.crt
# Optional: Required claims
- --oidc-required-claim=aud=kubernetesFor managed Kubernetes (EKS example):
# Update EKS cluster with OIDC
aws eks update-cluster-config \
--name my-cluster \
--identity-provider-config '{
"oidc": {
"identityProviderConfigName": "keycloak",
"issuerUrl": "https://keycloak.example.com/realms/kubernetes",
"clientId": "kubernetes",
"usernameClaim": "preferred_username",
"usernamePrefix": "oidc:",
"groupsClaim": "groups",
"groupsPrefix": "oidc:"
}
}'Step 3: Create RBAC for OIDC Users
Bind OIDC groups to Kubernetes roles:
# ClusterRoleBinding for admins group
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: oidc-cluster-admins
subjects:
- kind: Group
name: oidc:cluster-admins # Matches OIDC group with prefix
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
---
# RoleBinding for developers in production namespace
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: oidc-developers
namespace: production
subjects:
- kind: Group
name: oidc:developers
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: edit
apiGroup: rbac.authorization.k8s.io
---
# RoleBinding for specific user
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: oidc-user-jane
namespace: development
subjects:
- kind: User
name: oidc:jane@example.com
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: admin
apiGroup: rbac.authorization.k8s.ioStep 4: Configure kubectl with OIDC
Install kubelogin (OIDC helper):
# Install kubelogin
# macOS
brew install int128/kubelogin/kubelogin
# Linux
curl -LO https://github.com/int128/kubelogin/releases/latest/download/kubelogin_linux_amd64.zip
unzip kubelogin_linux_amd64.zip
sudo mv kubelogin /usr/local/bin/kubectl-oidc_loginConfigure kubeconfig for OIDC:
# ~/.kube/config
apiVersion: v1
kind: Config
clusters:
- name: production
cluster:
server: https://kubernetes.example.com:6443
certificate-authority-data: <base64-ca-cert>
contexts:
- name: production
context:
cluster: production
user: oidc-user
namespace: default
current-context: production
users:
- name: oidc-user
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
command: kubectl
args:
- oidc-login
- get-token
- --oidc-issuer-url=https://keycloak.example.com/realms/kubernetes
- --oidc-client-id=kubernetes
- --oidc-client-secret=kubernetes-client-secret
- --oidc-extra-scope=groups
- --oidc-extra-scope=emailStep 5: Configure Azure AD Integration
Register application in Azure AD:
# Create Azure AD application
az ad app create \
--display-name "Kubernetes Cluster" \
--sign-in-audience AzureADMyOrg \
--web-redirect-uris "http://localhost:8000"
# Add API permissions
az ad app permission add \
--id <app-id> \
--api 00000003-0000-0000-c000-000000000000 \
--api-permissions e1fe6dd8-ba31-4d61-89e7-88639da4683d=Scope
# Get tenant info
az account show --query tenantId -o tsvConfigure API server for Azure AD:
# API server flags for Azure AD
- --oidc-issuer-url=https://login.microsoftonline.com/<tenant-id>/v2.0
- --oidc-client-id=<application-id>
- --oidc-username-claim=email
- --oidc-groups-claim=groupsKubeconfig for Azure AD:
users:
- name: azure-ad-user
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
command: kubelogin
args:
- get-token
- --environment
- AzurePublicCloud
- --server-id
- <server-application-id>
- --client-id
- <client-application-id>
- --tenant-id
- <tenant-id>Step 6: Configure Okta Integration
Create Okta application:
# Okta configuration
# 1. Create new OIDC Web Application
# 2. Set redirect URIs: http://localhost:8000
# 3. Enable refresh tokens
# 4. Note client ID and secretAPI server configuration for Okta:
- --oidc-issuer-url=https://your-org.okta.com
- --oidc-client-id=<okta-client-id>
- --oidc-username-claim=email
- --oidc-groups-claim=groups
- --oidc-username-prefix=okta:
- --oidc-groups-prefix=okta:Step 7: Implement Token Refresh
Configure automatic token refresh:
# kubeconfig with refresh token support
users:
- name: oidc-user
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
command: kubectl
args:
- oidc-login
- get-token
- --oidc-issuer-url=https://keycloak.example.com/realms/kubernetes
- --oidc-client-id=kubernetes
- --oidc-client-secret=kubernetes-client-secret
- --grant-type=authcode-keyboard
- --token-cache-dir=~/.kube/cache/oidc-login
interactiveMode: IfAvailable
provideClusterInfo: trueStep 8: Audit OIDC Authentication
Enable audit logging for OIDC events:
# audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
# Log authentication events
- level: Metadata
users: ["system:anonymous"]
verbs: ["*"]
resources:
- group: "authentication.k8s.io"
resources: ["tokenreviews"]
# Log OIDC user actions at Request level
- level: Request
userGroups: ["oidc:*"]
verbs: ["create", "update", "patch", "delete"]Verification
Test OIDC authentication:
# Login with OIDC
kubectl oidc-login setup \
--oidc-issuer-url=https://keycloak.example.com/realms/kubernetes \
--oidc-client-id=kubernetes \
--oidc-client-secret=kubernetes-client-secret
# Verify token
kubectl auth whoami
# Check group membership
kubectl auth can-i --list
# Test specific permissions
kubectl auth can-i create deployments -n productionVerify API server configuration:
# Check API server logs for OIDC
kubectl logs -n kube-system kube-apiserver-<node> | grep -i oidc
# Verify OIDC discovery endpoint
curl https://keycloak.example.com/realms/kubernetes/.well-known/openid-configuration
# Validate JWT token
kubectl oidc-login get-token \
--oidc-issuer-url=https://keycloak.example.com/realms/kubernetes \
--oidc-client-id=kubernetes | jwt decode -Test RBAC bindings:
# Impersonate OIDC user
kubectl auth can-i create pods \
--as=oidc:jane@example.com \
-n production
# Impersonate OIDC group
kubectl auth can-i delete deployments \
--as-group=oidc:developers \
-n productionBest Practices
- Use group-based RBAC instead of individual user bindings
- Set appropriate token lifetimes (1-8 hours recommended)
- Enable PKCE for public clients
- Use secure redirect URIs (localhost for CLI)
- Implement token refresh for better UX
- Audit authentication events for security monitoring
- Use username/group prefixes to distinguish OIDC users
- Sync groups from IdP rather than manual assignment
- Test authentication flow before production rollout
- Document login procedures for users
Common Issues
Token validation failures:
- Verify issuer URL matches exactly
- Check clock skew between API server and IdP
- Ensure CA certificate is correct
Groups not appearing:
- Verify groups claim is configured in IdP
- Check groups are included in ID token (not just access token)
- Confirm group mapper is properly configured
kubectl authentication errors:
- Clear token cache:
rm -rf ~/.kube/cache/oidc-login - Verify kubeconfig exec configuration
- Check client secret is correct
Related Resources
📘 Go Further with Kubernetes Recipes
Love this recipe? There’s so much more! This is just one of 100+ hands-on recipes in our comprehensive Kubernetes Recipes book.
Inside the book, you’ll master:
- ✅ Production-ready deployment strategies
- ✅ Advanced networking and security patterns
- ✅ Observability, monitoring, and troubleshooting
- ✅ Real-world best practices from industry experts
“The practical, recipe-based approach made complex Kubernetes concepts finally click for me.”
👉 Get Your Copy Now — Start building production-grade Kubernetes skills today!
📘 Get All 100+ Recipes in One Book
Stop searching — get every production-ready pattern with detailed explanations, best practices, and copy-paste YAML.
Want More Kubernetes Recipes?
This recipe is from Kubernetes Recipes, our 750-page practical guide with hundreds of production-ready patterns.