From 71391db1326524dfd0c84fd36cb0ec5b3160a892 Mon Sep 17 00:00:00 2001 From: sax3l Date: Mon, 2 Nov 2026 15:48:51 +0100 Subject: [PATCH] fix(auth): fall back to the verified access token for the tenant claim Zitadel does not always copy urn:zitadel:iam:org:id into the id_token; the access token always carries it. Verify that token (issuer) before trusting its tenant. --- app/api/auth/callback/route.ts | 4 ++-- lib/oidc.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/api/auth/callback/route.ts b/app/api/auth/callback/route.ts index 5a01f1c..c784ca2 100644 --- a/app/api/auth/callback/route.ts +++ b/app/api/auth/callback/route.ts @@ -50,8 +50,8 @@ export async function GET(request: NextRequest) { } try { - const { idToken } = await exchangeCode(config, code, stored.verifier); - const verified = await verifyIdToken(config, idToken, stored.nonce); + const { idToken, accessToken } = await exchangeCode(config, code, stored.verifier); + const verified = await verifyIdToken(config, idToken, stored.nonce, accessToken); const session = await signSession({ sub: verified.sub, tenantId: verified.tenantId, diff --git a/lib/oidc.ts b/lib/oidc.ts index 8c5cdeb..ff8338d 100644 --- a/lib/oidc.ts +++ b/lib/oidc.ts @@ -128,6 +128,7 @@ export async function verifyIdToken( config: OidcConfig, idToken: string, expectedNonce: string, + accessToken?: string, ): Promise { const { payload } = await jwtVerify(idToken, keySet(config.issuer), { issuer: config.issuer,