Skip to content

Commit 8d7b387

Browse files
committed
Clean up pkce skip check for proxy providers
1 parent 89c4ec3 commit 8d7b387

File tree

2 files changed

+16
-4
lines changed

2 files changed

+16
-4
lines changed

Diff for: src/server/auth/handlers/token.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -91,16 +91,18 @@ export function tokenHandler({ provider, rateLimit: rateLimitConfig }: TokenHand
9191

9292
const { code, code_verifier } = parseResult.data;
9393

94-
// Skip local PKCE verification for proxy providers since the code_challenge is stored on the upstream server.
95-
// The code_verifier will be passed to the upstream server during token exchange.
96-
if (!(provider instanceof ProxyOAuthServerProvider)) {
94+
const skipLocalPkceValidation = provider instanceof ProxyOAuthServerProvider ? provider.skipLocalPkceValidation : false;
95+
96+
// Perform local PKCE validation unless explicitly delegated (e.g. by proxy provider)
97+
if (!skipLocalPkceValidation) {
9798
const codeChallenge = await provider.challengeForAuthorizationCode(client, code);
9899
if (!(await verifyChallenge(code_verifier, codeChallenge))) {
99100
throw new InvalidGrantError("code_verifier does not match the challenge");
100101
}
101102
}
102103

103-
const tokens = await provider.exchangeAuthorizationCode(client, code, code_verifier);
104+
// Passes the code_verifier to the provider if PKCE validation didn't occur locally
105+
const tokens = await provider.exchangeAuthorizationCode(client, code, skipLocalPkceValidation ? code_verifier : undefined);
104106
res.status(200).json(tokens);
105107
break;
106108
}

Diff for: src/server/auth/proxyProvider.ts

+10
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ export class ProxyOAuthServerProvider implements OAuthServerProvider {
4343
protected readonly _endpoints: ProxyEndpoints;
4444
protected readonly _verifyAccessToken: (token: string) => Promise<AuthInfo>;
4545
protected readonly _getClient: (clientId: string) => Promise<OAuthClientInformationFull | undefined>;
46+
47+
/**
48+
* Always true for proxy providers since PKCE validation happens at the upstream server.
49+
* Can consider adding to the base OAuthServerProvider interface if it becomes useful elsewhere.
50+
* This ensures that:
51+
* 1. We skip local PKCE validation (which would fail since we don't store challenges)
52+
* 2. The code_verifier is still passed through to the upstream server
53+
* 3. The upstream server performs the actual PKCE validation
54+
*/
55+
readonly skipLocalPkceValidation = true;
4656

4757
revokeToken?: (
4858
client: OAuthClientInformationFull,

0 commit comments

Comments
 (0)