Clean up pkce skip check for proxy providers

This commit is contained in:
Allen Zhou 2025-02-27 12:41:14 -08:00
commit 8d7b387545
No known key found for this signature in database
GPG key ID: 5817C145DE5C5556
2 changed files with 16 additions and 4 deletions

View file

@ -91,16 +91,18 @@ export function tokenHandler({ provider, rateLimit: rateLimitConfig }: TokenHand
const { code, code_verifier } = parseResult.data;
// Skip local PKCE verification for proxy providers since the code_challenge is stored on the upstream server.
// The code_verifier will be passed to the upstream server during token exchange.
if (!(provider instanceof ProxyOAuthServerProvider)) {
const skipLocalPkceValidation = provider instanceof ProxyOAuthServerProvider ? provider.skipLocalPkceValidation : false;
// Perform local PKCE validation unless explicitly delegated (e.g. by proxy provider)
if (!skipLocalPkceValidation) {
const codeChallenge = await provider.challengeForAuthorizationCode(client, code);
if (!(await verifyChallenge(code_verifier, codeChallenge))) {
throw new InvalidGrantError("code_verifier does not match the challenge");
}
}
const tokens = await provider.exchangeAuthorizationCode(client, code, code_verifier);
// Passes the code_verifier to the provider if PKCE validation didn't occur locally
const tokens = await provider.exchangeAuthorizationCode(client, code, skipLocalPkceValidation ? code_verifier : undefined);
res.status(200).json(tokens);
break;
}

View file

@ -43,6 +43,16 @@ export class ProxyOAuthServerProvider implements OAuthServerProvider {
protected readonly _endpoints: ProxyEndpoints;
protected readonly _verifyAccessToken: (token: string) => Promise<AuthInfo>;
protected readonly _getClient: (clientId: string) => Promise<OAuthClientInformationFull | undefined>;
/**
* Always true for proxy providers since PKCE validation happens at the upstream server.
* Can consider adding to the base OAuthServerProvider interface if it becomes useful elsewhere.
* This ensures that:
* 1. We skip local PKCE validation (which would fail since we don't store challenges)
* 2. The code_verifier is still passed through to the upstream server
* 3. The upstream server performs the actual PKCE validation
*/
readonly skipLocalPkceValidation = true;
revokeToken?: (
client: OAuthClientInformationFull,