From 93db4799c0ef9ae80f8aa2bc4a148c0828a6f780 Mon Sep 17 00:00:00 2001 From: ZacharyZcR Date: Sat, 3 Oct 2026 21:00:03 +0800 Subject: [PATCH] fix(sso): send the PKCE verifier for GitHub login (#1534) --- plugins/sso/src/backend/login.ts | 7 +++---- plugins/sso/tests/backend/sso.test.ts | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/plugins/sso/src/backend/login.ts b/plugins/sso/src/backend/login.ts index 1212cadbf..321f87094 100644 --- a/plugins/sso/src/backend/login.ts +++ b/plugins/sso/src/backend/login.ts @@ -194,7 +194,6 @@ export function createSsoLogin(ctx: PluginContext, store: ProviderStore) { config: OidcConfig, code: string, pending: PendingState, - withVerifier: boolean, ): Promise> { const response = await fetch(config.token_url, { method: "POST", @@ -208,7 +207,7 @@ export function createSsoLogin(ctx: PluginContext, store: ProviderStore) { client_secret: config.client_secret, code, redirect_uri: pending.backendCallback, - ...(withVerifier ? { code_verifier: pending.codeVerifier } : {}), + code_verifier: pending.codeVerifier, }), ...buildFetchOptions(config.ca_cert), } as RequestInit); @@ -231,7 +230,7 @@ export function createSsoLogin(ctx: PluginContext, store: ProviderStore) { code: string, pending: PendingState, ): Promise { - const tokenData = await exchangeCode(provider.config, code, pending, false); + const tokenData = await exchangeCode(provider.config, code, pending); const fetchOptions = buildFetchOptions(provider.config.ca_cert); const headers = { Authorization: `Bearer ${tokenData.access_token}`, @@ -341,7 +340,7 @@ export function createSsoLogin(ctx: PluginContext, store: ProviderStore) { pending: PendingState, ): Promise { const { config } = provider; - const tokenData = await exchangeCode(config, code, pending, true); + const tokenData = await exchangeCode(config, code, pending); let userInfo: Record | null = null; const claimSources: Record[] = []; diff --git a/plugins/sso/tests/backend/sso.test.ts b/plugins/sso/tests/backend/sso.test.ts index 4fea1b50b..0b6251557 100644 --- a/plugins/sso/tests/backend/sso.test.ts +++ b/plugins/sso/tests/backend/sso.test.ts @@ -1,3 +1,4 @@ +import { createHash } from "node:crypto"; import { afterEach, describe, expect, it, vi } from "vitest"; import { LEGACY_DDL, @@ -356,6 +357,19 @@ describe("the callback", () => { "GET", `/callback?code=abc&state=${url.searchParams.get("state")}`, ); + const exchange = vi + .mocked(fetch) + .mock.calls.find( + ([url]) => + String(url) === "https://github.com/login/oauth/access_token", + ); + const token = new URLSearchParams(String(exchange?.[1]?.body)); + const verifier = token.get("code_verifier"); + expect(verifier).toBeTruthy(); + expect(url.searchParams.get("code_challenge_method")).toBe("S256"); + expect(createHash("sha256").update(verifier!).digest("base64url")).toBe( + url.searchParams.get("code_challenge"), + ); expect(callback.body.identity).toMatchObject({ provider: String(created.body.id), subject: "42",