Skip to content

EMK - How to Setup Kubelogin

Estimated time to read: 4 minutes

This guide describes how to configure your local kubectl to authenticate using OIDC tokens with the kubectl oidc-login plugin (also known as kubelogin). This is required after configuring OIDC authentication on your cluster.


Prerequisites

Install the kubectl oidc-login plugin:

# Using krew (recommended)
kubectl krew install oidc-login

Or download the appropriate binaries for your system on gitHub.com.

Kubeconfig Setup

Configure your ~/.kube/config file to use OIDC authentication. Here's a complete example:

apiVersion: v1
kind: Config
clusters:
- cluster:
    certificate-authority-data: <base64-encoded-ca-cert>
    server: https://api.my-cluster.example.shoot.emk.example.cloud
  name: my-cluster
contexts:
- context:
    cluster: my-cluster
    user: oidc
  name: my-cluster
current-context: my-cluster
users:
- name: oidc
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1beta1
      args:
      - oidc-login
      - get-token
      - --oidc-issuer-url=https://your-issuer.example.com
      - --oidc-client-id=<your-client-id>
      - --oidc-extra-scope=email
      - --oidc-extra-scope=offline_access
      - --oidc-extra-scope=profile
      command: kubectl
      env: null
      interactiveMode: IfAvailable
      provideClusterInfo: false

You can configure multiple clusters in a single kubeconfig file, all using the same OIDC user:

apiVersion: v1
kind: Config
clusters:
- cluster:
    certificate-authority-data: <base64-encoded-ca-cert>
    server: https://api.my-cluster-prod.example.shoot.emk.example.cloud
  name: my-cluster-prod
- cluster:
    certificate-authority-data: <base64-encoded-ca-cert>
    server: https://api.my-cluster-staging.example.shoot.emk.example.cloud
  name: my-cluster-staging
contexts:
- context:
    cluster: my-cluster-prod
    user: oidc
  name: my-cluster-prod
- context:
    cluster: my-cluster-staging
    user: oidc
  name: my-cluster-staging
current-context: my-cluster-staging
users:
- name: oidc
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1beta1
      args:
      - oidc-login
      - get-token
      - --oidc-issuer-url=https://your-issuer.example.com
      - --oidc-client-id=<your-client-id>
      - --oidc-extra-scope=email
      - --oidc-extra-scope=offline_access
      - --oidc-extra-scope=profile
      command: kubectl
      env: null
      interactiveMode: IfAvailable
      provideClusterInfo: false

Switch between clusters using:

kubectl config use-context my-cluster-prod
kubectl config use-context my-cluster-staging
Configuration Parameters
Parameter
Description
--oidc-issuer-url The issuer URL of your identity provider. Must match the url in your Structured Authentication configuration.
--oidc-client-id The client ID registered with your identity provider. Must match one of the audiences in your configuration.
--oidc-extra-scope Additional OAuth2 scopes to request. Common scopes: email, profile, groups, offline_access.

First Authentication

When you run your first kubectl command, the OIDC login plugin will:

  1. Open your browser automatically
  2. Redirect you to your identity provider's login page
  3. After successful authentication, receive the token and store it locally
  4. Use the token for subsequent kubectl commands

Example first command:

kubectl get pods
# Browser will open for authentication
# After login, the command will execute

Token Caching

The kubectl oidc-login plugin caches tokens locally (typically in ~/.kube/cache/oidc-login/). Tokens are automatically refreshed when expired if your identity provider supports the offline_access scope.

Token Refresh

Always include --oidc-extra-scope=offline_access to enable automatic token refresh. Without this scope, you'll need to re-authenticate in the browser every time the token expires.

Troubleshooting

Browser doesn't open automatically

Try adding the --oidc-use-pkce flag for better compatibility:

kubectl oidc-login get-token \
  --oidc-issuer-url=https://your-issuer.example.com \
  --oidc-client-id=<your-client-id>

You can also add this flag to your kubeconfig:

args:
- oidc-login
- get-token
- --oidc-issuer-url=https://your-issuer.example.com
- --oidc-client-id=<your-client-id>
- --oidc-use-pkce
- --oidc-extra-scope=email
- --oidc-extra-scope=offline_access
- --oidc-extra-scope=profile

Token expired and not refreshing

Verify offline_access scope is configured:

Check your kubeconfig includes --oidc-extra-scope=offline_access.

Clear the token cache:

rm -rf ~/.kube/cache/oidc-login/

Re-authenticate:

Run any kubectl command to trigger a new authentication:

kubectl get pods

Groups not appearing in token

Check identity provider configuration:

  • Verify that your identity provider includes groups in the JWT token
  • Some providers require additional configuration to include group claims

Request groups scope:

Add the groups scope if required by your provider:

args:
- oidc-login
- get-token
- --oidc-issuer-url=https://your-issuer.example.com
- --oidc-client-id=<your-client-id>
- --oidc-extra-scope=email
- --oidc-extra-scope=offline_access
- --oidc-extra-scope=profile
- --oidc-extra-scope=groups

Decode your token:

Verify what claims are present in your token:

  1. Run a kubectl command to get a token
  2. Copy the token from ~/.kube/cache/oidc-login/
  3. Decode it at jwt.io
  4. Check if the groups claim is present

Authentication fails with "Unauthorized"

Verify issuer URL:

Ensure the --oidc-issuer-url matches exactly what's configured in your cluster's Structured Authentication.

Check client ID:

Verify the --oidc-client-id matches one of the audiences in your cluster's authentication configuration.

Check RBAC permissions:

Even if authentication succeeds, you need proper RBAC permissions. See Configuring User Permissions with RBAC.

Advanced Configuration

Some identity providers require a specific redirect URI:

args:
- oidc-login
- get-token
- --oidc-issuer-url=https://your-issuer.example.com
- --oidc-client-id=<your-client-id>
- --oidc-redirect-url-hostname=localhost:8000

If you prefer to manually copy the authentication URL:

args:
- oidc-login
- get-token
- --oidc-issuer-url=https://your-issuer.example.com
- --oidc-client-id=<your-client-id>
- --skip-open-browser

Specify a custom browser command:

args:
- oidc-login
- get-token
- --oidc-issuer-url=https://your-issuer.example.com
- --oidc-client-id=<your-client-id>
- --browser-command="firefox %s"