Skip to content

feat: Add an option to send the OIDC ID token instead of the access token - #197

Merged
gianlucam76 merged 1 commit into
projectsveltos:mainfrom
gianlucam76:oidc-token-type
Oct 8, 2026
Merged

gianlucam76 merged 1 commit into
projectsveltos:mainfrom
gianlucam76:oidc-token-type

Conversation

@gianlucam76

Copy link
Copy Markdown
Member

After an OIDC login the dashboard sent the access token to the backend as the bearer token. The Kubernetes API server, and an OIDC proxy such as kube-oidc-proxy in front of it, only verify signed JWTs. Some providers issue access tokens they cannot verify: NetIQ/SIAM, for instance, returns an encrypted JWT (JWE), so every request was refused with a 401 even though the login succeeded. The ID token is a signed JWT and is the token Kubernetes tooling such as kubelogin authenticates with.

The new setting oidcTokenType chooses which token is sent: access_token, the default, so nothing changes for existing setups, or id_token. A single function picks the token for both the login callback and the silent token renewal. When id_token is set and the provider returns no ID token, the user is sent back to the login page with "Unauthorized".

What needs to be set:

Helm chart (dashboard): auth.oidc.tokenType: id_token
Container environment: OIDC_TOKEN_TYPE=id_token
Local development: VITE_OIDC_TOKEN_TYPE=id_token

Set it when the access token returned by the provider is not a signed JWT, that is when ui-backend reports a token it cannot verify, or when the OIDC proxy logs auth_method none for a user who logged in successfully. The provider has to return an ID token, so the "openid" scope must be requested, which it is by default. The ID token lifetime should cover a session: token renewal is driven by the access token's expiry.

The value is passed to the dashboard through the OIDC_TOKEN_TYPE variable of the runtime config (scripts/config.template.js and docker-entrypoint.sh). The dashboard Helm chart option is added in the helm-charts repository.

…oken

After an OIDC login the dashboard sent the access token to the backend as
the bearer token. The Kubernetes API server, and an OIDC proxy such as
kube-oidc-proxy in front of it, only verify signed JWTs. Some providers
issue access tokens they cannot verify: NetIQ/SIAM, for instance, returns an
encrypted JWT (JWE), so every request was refused with a 401 even though the
login succeeded. The ID token is a signed JWT and is the token Kubernetes
tooling such as kubelogin authenticates with.

The new setting oidcTokenType chooses which token is sent: access_token,
the default, so nothing changes for existing setups, or id_token. A single
function picks the token for both the login callback and the silent token
renewal. When id_token is set and the provider returns no ID token, the user
is sent back to the login page with "Unauthorized".

What needs to be set:

  Helm chart (dashboard):  auth.oidc.tokenType: id_token
  Container environment:   OIDC_TOKEN_TYPE=id_token
  Local development:       VITE_OIDC_TOKEN_TYPE=id_token

Set it when the access token returned by the provider is not a signed JWT,
that is when ui-backend reports a token it cannot verify, or when the OIDC
proxy logs auth_method none for a user who logged in successfully. The
provider has to return an ID token, so the "openid" scope must be requested,
which it is by default. The ID token lifetime should cover a session: token
renewal is driven by the access token's expiry.

The value is passed to the dashboard through the OIDC_TOKEN_TYPE variable of
the runtime config (scripts/config.template.js and docker-entrypoint.sh).
The dashboard Helm chart option is added in the helm-charts repository.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@matthewgreenwaldagility

Copy link
Copy Markdown

Thanks for this, it matches what we ran into. We use Okta with only the org authorization server (no custom authorization servers). Its access tokens are meant for Okta's own APIs and can't be validated by the Kubernetes API server, but the ID token works fine, the same way kubelogin uses it. Without this option our only workaround was running Dex as a broker. Sending the ID token would let us drop that entirely. Happy to help test once it's released.

@gianlucam76
gianlucam76 merged commit 3cbc6bf into projectsveltos:main Oct 8, 2026
1 check passed
@gianlucam76
gianlucam76 deleted the oidc-token-type branch October 8, 2026 06:23
@gianlucam76

Copy link
Copy Markdown
Member Author

Thanks @matthewgreenwaldagility

I released dashboard helm chart v1.16.1 with this.

let me know if you get a chance to test this and there are issues. Thank you!

@matthewgreenwaldagility

Copy link
Copy Markdown

@gianlucam76 What was the design decision for dashboard that led to using kube-oidc-proxy in the first place?

@matthewgreenwaldagility

Copy link
Copy Markdown

@gianlucam76 I opened this issue: projectsveltos/ui-backend#189

@gianlucam76

Copy link
Copy Markdown
Member Author

Thank you so much @matthewgreenwaldagility. I was just reading that. Will work on it and will try to have something in the next few days. I might bug with some questions (if you use slack please fell free to join the projectsveltos channel).

Regarding current implementation it came from an explicit request from a large company using sveltos. While they don't use kube-oidc-proxy i used it to come up with a scenario I can test against that was close to what they have.

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.

2 participants