Skip to content

grafana: disable PKCE for the generic_oauth flow#600

Merged
ExtraToast merged 1 commit into
mainfrom
fix/grafana-oidc-pkce
Jun 8, 2026
Merged

grafana: disable PKCE for the generic_oauth flow#600
ExtraToast merged 1 commit into
mainfrom
fix/grafana-oidc-pkce

Conversation

@ExtraToast

Copy link
Copy Markdown
Owner

Grafana is a confidential OAuth2 client authenticated with CLIENT_SECRET_BASIC. PKCE is designed for public clients that cannot protect a secret; for confidential clients the client secret already authenticates the token exchange.

With use_pkce: true, Grafana generates a code_verifier, stores it in a browser session cookie alongside the OAuth state, and sends it in the token request. If that cookie is missing or invalid (different browser tab, browser restart, Safari ITP expiry, a proxy stripping Set-Cookie), Grafana omits the verifier from the token POST. Spring Authorization Server stored the code_challenge at the authorize step, so it sees a stored challenge with no matching verifier and rejects the request — surfacing as "Failed to get token from provider" on the Grafana login page.

use_pkce: false removes the browser-state dependency entirely. The auth-api client registration remains requirePkce: false, so the flow is: authorize → code (with state, no PKCE) → CLIENT_SECRET_BASIC-authenticated token exchange.

After merge: a Grafana pod restart is required (kubectl -n observability rollout restart deploy grafana) for the new config to take effect. If Grafana login still fails after the restart, also verify that the Vault secrets at secret/auth-api (auth.clients.grafana.secret) and secret/platform/observability (grafana.oauth_client_secret) are identical — re-running tmp.sh's pair call and restarting both auth-api and Grafana will re-align them.

Grafana is a confidential client authenticated with CLIENT_SECRET_BASIC.
PKCE is designed for public clients that cannot protect a client secret;
for confidential clients the client secret already authenticates the token
exchange and PKCE adds no meaningful security.

With use_pkce=true, Grafana generates a code_verifier, stores it in a
browser session cookie alongside the OAuth state, then sends it in the
token request. If that cookie is absent or invalid (different tab, browser
restart, Safari ITP expiry, proxy stripping Set-Cookie), Grafana omits the
verifier from the token request. Spring Authorization Server stored the
code_challenge at the authorize step, so it now sees a stored challenge
with no matching verifier and rejects the exchange — surfacing as "Failed
to get token from provider" on the login page.

Setting use_pkce=false removes the browser-state dependency and leaves
the auth-api client registration unchanged (requirePkce=false). The
flow is: authorize → cookie-free state param → code → secret-authenticated
token exchange.
@ExtraToast ExtraToast added the bug Something isn't working label Jun 8, 2026
@ExtraToast ExtraToast self-assigned this Jun 8, 2026
@ExtraToast ExtraToast merged commit 2b184d5 into main Jun 8, 2026
222 of 247 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant