gitroomhq/postiz-app · error · HttpException
code_challenge is required for this client
Error message
code_challenge is required for this client
What it means
Thrown when a public dynamic client (token_endpoint_auth_method=none, e.g. an SPA, CLI, or AI agent like an MCP client) sends an authorization request without a PKCE code_challenge. RFC 7636 PKCE is mandatory for public clients because they have no client secret to protect code interception.
Source
Thrown at libraries/nestjs-libraries/src/database/prisma/oauth/oauth.service.ts:200
redirectUri?: string;
codeChallenge?: string;
codeChallengeMethod?: string;
}
) {
const app = await this._oauthRepository.getAppByClientId(clientId);
if (!app) {
throw new HttpException('Invalid client_id', HttpStatus.BAD_REQUEST);
}
// Dynamically registered clients must use their registered redirect_uris
// and PKCE; statically registered apps keep the existing lenient flow
if (app.dynamic) {
const registered: string[] = JSON.parse(app.redirectUris || '[]');
if (!options?.redirectUri || !registered.includes(options.redirectUri)) {
throw new HttpException('Invalid redirect_uri', HttpStatus.BAD_REQUEST);
}
if (app.tokenEndpointAuthMethod === 'none' && !options?.codeChallenge) {
throw new HttpException(
'code_challenge is required for this client',
HttpStatus.BAD_REQUEST
);
}
if (
options?.codeChallenge &&
options?.codeChallengeMethod &&
options.codeChallengeMethod !== 'S256'
) {
throw new HttpException(
'Only the S256 code_challenge_method is supported',
HttpStatus.BAD_REQUEST
);
}
}
return app;
}View on GitHub (pinned to 0f1647f749)
Solutions
- Enable PKCE (S256) in your OAuth client library and retry the authorization request
- Verify code_challenge and code_challenge_method=S256 are present and URL-encoded in the authorize URL
- If the client can keep a secret, re-register with a confidential token_endpoint_auth_method instead
Example fix
// before
const client = new AuthorizationCode({
clientId,
redirectUri,
tokenEndpointAuthMethod: 'none',
});
// after
const client = new AuthorizationCode({
clientId,
redirectUri,
tokenEndpointAuthMethod: 'none',
});
const url = client.authorizeURL({
scope: 'openid',
code_challenge: await pkceChallengeFromVerifier(verifier),
code_challenge_method: 'S256',
}); Defensive patterns
Strategy: validation
Validate before calling
if (client.tokenEndpointAuthMethod === 'none' && !codeChallenge) {
codeChallenge = await computeS256Challenge(generateVerifier());
} Type guard
const needsPkce = (app: {dynamic: boolean; tokenEndpointAuthMethod: string}) => app.dynamic && app.tokenEndpointAuthMethod === 'none'; Try / catch
try { await authorize(req); } catch (e) { if (e?.response?.status === 400 && /code_challenge/.test(e.message)) { return restartFlowWithPkce(); } throw e; } Prevention
- Always use an OAuth library with PKCE S256 enabled for public clients
- Generate and persist the verifier before building the authorize URL
When it happens
Trigger: Authorization request for a dynamic client with tokenEndpointAuthMethod='none' and no code_challenge parameter in the query string, or the parameter name misspelled/mangled by your OAuth library config.
Common situations: Using a plain fetch/redirect flow instead of an OAuth library with PKCE enabled; library has PKCE disabled by default (e.g. some SDKs require usePkce: true / code_challenge_method config); switching a confidential client to public without updating the client code.
Related errors
- Only the S256 code_challenge_method is supported
- Invalid redirect_uri
- { error: 'invalid_grant', error_description: 'code_verifier
- { error: 'invalid_grant', error_description: 'Invalid code_v
- Unauthorized
AI-assisted analysis of gitroomhq/postiz-app@0f1647f749 (2026-08-27).
Data as JSON: /api/errors/57d76613a03662b5.
Report an issue: GitHub.