How it works
Kubernetes’ API server can validate JSON Web Tokens (JWTs) issued by an external OIDC provider. When a user runskubectl, the OIDC kubeconfig calls a local helper that handles login interactively, then attaches the resulting token to every API request.
OIDC flow
OIDC flow
The flow has four stages: login, token, validate, and authorize.
1
Login
The user runs a
kubectl command. kubectl sees the exec plugin in the OIDC kubeconfig and invokes kubectl-together_login. The plugin opens the user’s default browser and redirects to the IdP’s authorization endpoint with a PKCE challenge. The user signs in to the IdP with their organization credentials.2
Token
The IdP issues a signed ID token (a JWT) and redirects back to
http://localhost:8000 or :18000, where the plugin is listening. The plugin caches the token under $HOME/.kube/cache/oidc-login/ and returns it to kubectl.3
Validate
kubectl sends the API request with the token in the Authorization: Bearer … header. The Kubernetes API server validates the token by fetching the IdP’s public signing keys from its OIDC discovery document (<issuer_url>/.well-known/openid-configuration), verifying the token’s signature, and checking that the iss and aud claims match the issuer URL and client ID configured on the cluster. A failure here returns 401 Unauthorized.4
Authorize
The API server reads the configured username claim (
email, preferred_username, or sub) and uses it as the user identity for RBAC. It evaluates ClusterRoleBindings and RoleBindings to decide whether the request is allowed. No matching binding returns 403 Forbidden.Username claim
The username claim is the field in the OIDC token that Kubernetes uses as the identity for RBAC. The supported claims areemail, preferred_username, and sub. Choose one that your IdP reliably provides.
The claim sets the format of the identity, which is the exact value you pass as --user when you create RBAC bindings:
emailproduces[email protected], used as-is.subproduces<issuer_url>#<sub_value>, for examplehttps://accounts.google.com#105010678054620911233.preferred_usernameproduces<issuer_url>#<username>, for examplehttps://login.microsoftonline.com/<TENANT_ID>/v2.0#[email protected].
email claim gives the simplest RBAC setup, because its value needs no issuer prefix.
Requirements
To set up OIDC authentication, you need:- An OIDC-compatible identity provider, such as Google, Okta, Auth0, or Entra ID.
- A GPU cluster with external OIDC enabled. You can enable OIDC only when you create the cluster.
kubectlinstalled locally.- The cluster’s admin kubeconfig, which the admin uses to create RBAC bindings. Only project admins can download it.
Set up the cluster (admin)
Complete these tasks as a project admin. When you’re done, share this page with your team members so they can connect to the cluster.1
Create an OIDC application in your identity provider
Create an OIDC client or application in your identity provider with these settings:
- Redirect URIs:
http://localhost:8000andhttp://localhost:18000. - Auth method: Authorization code flow with Proof Key for Code Exchange (PKCE).
- Scopes: Always include
openid. Addemailif your username claim isemail, orprofileif it’spreferred_username. Thesubclaim needs no additional scopes.
--oidc-extra-scope, so your IdP application only needs to allow them.Record the application’s Issuer URL and Client ID, which you enter when you enable OIDC on the cluster. If your provider requires a client secret, record the Client Secret too. Team members set it on their own machines, as described in Set the OIDC client secret.Issuer URL formats by provider:
- Auth0: The issuer URL must end with a trailing slash, for example
https://your-tenant.auth0.com/. Without it, OIDC discovery fails. - Okta: Use the full authorization server URL, including
/oauth2/default, for examplehttps://your-org.okta.com/oauth2/default. The bare Okta domain returnsinvalid_client. - Google: The issuer URL is always
https://accounts.google.com.
2
Enable external OIDC on the cluster
- Go to GPU Clusters → Create cluster, and set Orchestration to Kubernetes.
- Under Cluster add-ons, set Use custom OIDC to Yes. The OIDC fields below the toggle become editable.
- Optionally, select a Quick setup preset (Google, Okta, Auth0, or Entra ID) to prefill provider defaults.
- Enter the Issuer URL and Client ID from your OIDC application, and set Username Claim to
email,preferred_username, orsub. - Wait for Provider verification to check the discovery document, reachability, and required claims.
- Complete the rest of the form, then select Create Cluster and Confirm & Create.
3
Grant RBAC permissions
OIDC users have no access to the cluster until you create Kubernetes RBAC bindings for their identities. Create the bindings with the admin kubeconfig, not the OIDC kubeconfig, because OIDC users can’t grant themselves permissions.The console doesn’t configure a groups claim, so bind each user individually. To bind groups instead, you need
oidc_config.group_claim, which you can set only when you create the cluster through the API or SDK.Set --user to the exact identity Kubernetes extracts from the token. Its format depends on your username claim:- email
- sub
- preferred_username
Connect to the cluster (user)
Each team member completes these tasks on their local machine.1
Download the OIDC kubeconfig
Only project admins can see the OIDC kubeconfig in the console. The file contains no credentials, so a project admin can share it with editors. If you’re a project editor, ask a project admin for the file and save it to
$HOME/.kube/my-cluster-oidc.yaml.If you’re a project admin, download it once the cluster’s status is Ready:- Open the cluster details page.
- In the sidebar, find OIDC Kubeconfig and select View.
- Copy the kubeconfig content and save it to
$HOME/.kube/my-cluster-oidc.yaml:
2
Install the login helper
The OIDC kubeconfig calls an exec plugin that handles browser-based login and token caching. Which plugin you install depends on what the OIDC Kubeconfig dialog’s Quick setup shows. If you’re a project editor, ask the project admin who shared your kubeconfig.If it shows Verify the installation:
kubelogin, your cluster is a Together-managed OIDC cluster, and its kubeconfig calls kubectl oidc-login. Install int128/kubelogin with brew install kubelogin or kubectl krew install oidc-login.If it shows together-login, download the binary for your platform from the together-kubelogin releases, verify its checksum, and move it onto your PATH:- macOS Apple Silicon
- macOS Intel
- Linux amd64
- Linux arm64
3
Set the OIDC client secret
The kubeconfig uses PKCE (
S256) by default, so most providers don’t require a client secret, and you can skip this task. Some providers, such as Google, require one even for desktop or native PKCE flows. If yours does, get the secret from your admin and set it for the current session:4
Verify access
Test your access with the OIDC kubeconfig:A browser opens for login. Sign in with your IdP credentials, then check the result:
- Success: The command lists the cluster’s nodes. You’re authenticated and authorized.
403 Forbidden: Authentication worked, but no RBAC binding exists for your identity. Ask your admin to complete Grant RBAC permissions.
get nodes returns 403 even when you have access. Verify with get pods instead.Revoking access
To revoke a user’s access:- Remove their RBAC binding from the cluster:
- Remove the user from your IdP, or from the relevant group, to prevent new tokens from being issued.
Token lifetime and refresh
OIDC tokens are short-lived (typically one hour, depending on your IdP configuration). When a token expires, the login plugin opens a browser automatically so you can sign in again. If your IdP supports refresh tokens, the plugin can renew the token without a login prompt. The plugin caches tokens locally in$HOME/.kube/cache/oidc-login/. To force a fresh login, clear the cache:
kubelogin, run kubectl oidc-login clean instead. Deleting the cache directory works with either plugin:
Troubleshooting
403 Forbidden
Authentication succeeded, but no RBAC binding grants your identity the required permissions.
On Together-managed OIDC clusters, verify with
get pods: If the OIDC Kubeconfig dialog’s Quick setup shows kubelogin rather than together-login, your cluster grants namespace-scoped RBAC, and get nodes returns 403 Forbidden even when authentication works. Run get pods instead:- Confirm the exact identity your username claim produces, such as
[email protected]or an issuer-prefixedsubvalue. The binding’s--uservalue must match it. - Ask a project admin to create a ClusterRoleBinding or RoleBinding for your identity.
- If your role recently changed, clear the OIDC token cache so the next login picks up the new access.
401 Unauthorized or “provide credentials”
Token validation failed at the API server.
Fix:
- Check the cluster’s OIDC configuration against the token. The issuer URL must match the token’s
issclaim, the client ID must match itsaudclaim, and the token must contain the username claim. - Clear cached tokens and retry:
client_secret is missing
Your IdP requires a client secret that wasn’t provided.
Fix:
Browser login doesn’t open
Fix:- Ensure
kubectl-together_loginis installed and on your PATH. - Run
kubectl together-login --helpto verify.
Security best practices
- Use short-lived OIDC tokens, and rely on your IdP for user lifecycle (joiners, movers, leavers).
- Keep the admin kubeconfig restricted to break-glass scenarios. Use OIDC for day-to-day access.
- Use
emailas the username claim for the simplest RBAC setup. Other claims require issuer-prefixed--uservalues.