Skip to content

kubernetes exec-credential command for OIDC Authorization flow with PKCE#1840

Merged
sjana-do merged 6 commits into
digitalocean:mainfrom
d-honeybadger:doks-sso-authorization-flow
May 12, 2026
Merged

kubernetes exec-credential command for OIDC Authorization flow with PKCE#1840
sjana-do merged 6 commits into
digitalocean:mainfrom
d-honeybadger:doks-sso-authorization-flow

Conversation

@d-honeybadger
Copy link
Copy Markdown
Contributor

@d-honeybadger d-honeybadger commented May 7, 2026

Adds a set of flags to doctl cluster kubernetes kubeconfig exec-credential command to be able to handle OIDC authorization.
Currently, doctl kubernetes kubeconfig exec-credential is used to fetch a DO PAT from DOKS API, and this PAT is used by kubectl to authenticate inside the k8s cluster.
The additional flags enable doctl kubernetes kubeconfig exec-credential to instead receive a token (ID token) from an OIDC idendity provider such as Okta, Auth0.

The authorization flow implemented here is similar to how OSS kubectl plugins do it (e.g. https://github.com/int128/kubelogin) but with our own implementation we get seamless UX (users don't have to install and configure third-party plugins) and flexibility in adjusting & fixing any issies.

@@ -0,0 +1,162 @@
<!DOCTYPE html>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI-generated as I'm no html/css expert
This is what it looks like

Image

@@ -0,0 +1,164 @@
<!DOCTYPE html>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI-generated as I'm not an htlm/css expert
Here's what it looks like

Image

@d-honeybadger d-honeybadger force-pushed the doks-sso-authorization-flow branch from d5c453d to b8b6e22 Compare May 7, 2026 15:52
Comment thread commands/doit.go

// in case we ever want to change this, or let folks configure it...
func defaultConfigHome() string {
var defaultConfigHome = func() string {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So that it can be stubbed in tests.

Comment thread commands/kubernetes.go
return filepath.Join(kubeconfigCachePath(), id+".json")
}

func cachedSSOExecCredentialPath(id string) string {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separate files for SSO tokens

@d-honeybadger d-honeybadger force-pushed the doks-sso-authorization-flow branch from b8b6e22 to 84c9897 Compare May 7, 2026 16:08
Comment thread internal/kubernetes/sso/sso.go Outdated

server := &http.Server{
Handler: t.ssoServer,
Addr: fmt.Sprintf(":%d", t.port),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

":8080" listens on every interface, the browser only needs to reach localhost. Suggested to use fmt.Sprintf("127.0.0.1:%d", t.port)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, thanks!

Comment thread internal/kubernetes/sso/sso.go Outdated
return "", time.Time{}, errors.New("no ID token found")
}

return idToken, token.Expiry, nil
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we verify the ID token locally before returning it. We are pulling id_token out of the token response and forward it to kubectl as-is — no signature, iss, aud, or exp check

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This command doesn't authorize the user to do anything though, it just returns a token that will be passed to kube-apiserver which will perform all the necessary verifications. I added a simple verification, but I think we can be pretty minimal here and not duplicate kube-apiserver's job - WDYT?

Comment thread commands/kubernetes.go Outdated
@RohithSangati
Copy link
Copy Markdown
Contributor

Adds a set of flags to doctl kubernetes kubeconfig exec-credential command to be able to handle OIDC authorization. Currently, doctl kubernetes kubeconfig exec-credential is used to fetch a DO PAT from DOKS API, and this PAT is used by kubectl to authenticate inside the k8s cluster. The additional flags enable doctl kubernetes kubeconfig exec-credential to instead receive a token (ID token) from an OIDC idendity provider such as Okta, Auth0.

The authorization flow implemented here is similar to how OSS kubectl plugins do it (e.g. https://github.com/int128/kubelogin) but with our own implementation we get seamless UX (users don't have to install and configure third-party plugins) and flexibility in adjusting & fixing any issies.

Just a small clarification — should the command here be doctl kubernetes cluster kubeconfig exec-credential instead of doctl kubernetes kubeconfig exec-credential, since from the code it looks like kubeconfig is a child of the cluster command? I might be misunderstanding something, so wanted to confirm once.

@d-honeybadger d-honeybadger force-pushed the doks-sso-authorization-flow branch from 559a4b7 to 6c6ed92 Compare May 11, 2026 13:10
@d-honeybadger
Copy link
Copy Markdown
Contributor Author

Just a small clarification — should the command here be doctl kubernetes cluster kubeconfig exec-credential instead of doctl kubernetes kubeconfig exec-credential, since from the code it looks like kubeconfig is a child of the cluster command? I might be misunderstanding something, so wanted to confirm once.

Correct, I forgot the cluster part in this PR's description (it's a loong subcommand 😄 ). Fixed!

@sjana-do sjana-do merged commit 610a9a2 into digitalocean:main May 12, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants