From 2ef0c0d8e14fcd5ff1c06f6113ffaf2792b9d4c9 Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Fri, 16 Oct 2026 09:24:51 +0200 Subject: [PATCH] fix: emit a single email claim in job OIDC tokens (#11804) * fix: emit a single email claim in job OIDC tokens Bumps the EE ref to drop the duplicate standard email claim from the job token mint, and asserts the raw payload carries one email key. Co-Authored-By: Claude Opus 5.5 * test: note the single-email check in the OIDC claim test doc Co-Authored-By: Claude Opus 5.5 * chore: update ee-repo-ref to d29a7c0dad120e137105b1186d0bbe3ea1504b5d This commit updates the EE repository reference after PR #886 was merged in windmill-ee-private. Previous ee-repo-ref: d64df5c1787e4404c99a41a97fca22668a669c4d New ee-repo-ref: d29a7c0dad120e137105b1186d0bbe3ea1504b5d Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 5.5 Co-authored-by: windmill-internal-app[bot] --- backend/ee-repo-ref.txt | 2 +- backend/tests/job_token_scopes.rs | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/backend/ee-repo-ref.txt b/backend/ee-repo-ref.txt index 3b37119381..8ba0c97c0b 100644 --- a/backend/ee-repo-ref.txt +++ b/backend/ee-repo-ref.txt @@ -1 +1 @@ -3b6bd2b15d9bddb0bb8f1de08b30b897db0415b4 +d29a7c0dad120e137105b1186d0bbe3ea1504b5d diff --git a/backend/tests/job_token_scopes.rs b/backend/tests/job_token_scopes.rs index f805168bfa..71ecaa444e 100644 --- a/backend/tests/job_token_scopes.rs +++ b/backend/tests/job_token_scopes.rs @@ -363,7 +363,8 @@ async fn test_deploy_without_the_field_keeps_the_restriction( Ok(()) } -/// The OIDC `job_token_scopes` claim states the scopes of the token that asked for it. +/// The OIDC `job_token_scopes` claim states the scopes of the token that asked for it, in a +/// payload that strict JSON parsers accept (no duplicate `email` key). #[cfg(all(feature = "enterprise", feature = "private", feature = "openidconnect"))] #[sqlx::test(fixtures("base"))] async fn test_oidc_claim_carries_the_presented_scopes(db: Pool) -> anyhow::Result<()> { @@ -404,10 +405,12 @@ async fn test_oidc_claim_carries_the_presented_scopes(db: Pool) -> any let status = resp.status(); let id_token = resp.text().await?; assert_eq!(status, StatusCode::OK, "{id_token}"); - let payload = id_token.split('.').nth(1).expect("a JWT payload"); - let claims: serde_json::Value = serde_json::from_slice( - &base64::engine::general_purpose::URL_SAFE_NO_PAD.decode(payload)?, - )?; + let payload = base64::engine::general_purpose::URL_SAFE_NO_PAD + .decode(id_token.split('.').nth(1).expect("a JWT payload"))?; + // serde_json keeps the last of duplicate keys, so count them on the raw payload. + let raw = String::from_utf8(payload.clone())?; + assert_eq!(raw.matches("\"email\":").count(), 1, "{raw}"); + let claims: serde_json::Value = serde_json::from_slice(&payload)?; assert_eq!(claims["job_token_scopes"], expected, "{job}"); }