{"record":{"id":"4d7b44f54dc071ec","repo":"gitroomhq/postiz-app","slug":"only-the-s256-code-challenge-method-is-supported","errorCode":null,"errorMessage":"Only the S256 code_challenge_method is supported","messagePattern":"Only the S256 code_challenge_method is supported","errorType":"http","errorClass":"HttpException","httpStatus":400,"severity":"error","filePath":"libraries/nestjs-libraries/src/database/prisma/oauth/oauth.service.ts","lineNumber":210,"sourceCode":"    // Dynamically registered clients must use their registered redirect_uris\n    // and PKCE; statically registered apps keep the existing lenient flow\n    if (app.dynamic) {\n      const registered: string[] = JSON.parse(app.redirectUris || '[]');\n      if (!options?.redirectUri || !registered.includes(options.redirectUri)) {\n        throw new HttpException('Invalid redirect_uri', HttpStatus.BAD_REQUEST);\n      }\n      if (app.tokenEndpointAuthMethod === 'none' && !options?.codeChallenge) {\n        throw new HttpException(\n          'code_challenge is required for this client',\n          HttpStatus.BAD_REQUEST\n        );\n      }\n      if (\n        options?.codeChallenge &&\n        options?.codeChallengeMethod &&\n        options.codeChallengeMethod !== 'S256'\n      ) {\n        throw new HttpException(\n          'Only the S256 code_challenge_method is supported',\n          HttpStatus.BAD_REQUEST\n        );\n      }\n    }\n\n    return app;\n  }\n\n  async createAuthorizationCode(\n    oauthAppId: string,\n    userId: string,\n    organizationId: string,\n    pkce?: {\n      codeChallenge?: string;\n      codeChallengeMethod?: string;\n      redirectUri?: string;\n    }","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/gitroomhq/postiz-app/blob/0f1647f7491a217d43eb5ae7a480484bdf0aff3e/libraries/nestjs-libraries/src/database/prisma/oauth/oauth.service.ts#L192-L228","documentation":"Thrown when the authorization request includes a code_challenge with a code_challenge_method other than S256. This server deliberately supports only the S256 (SHA-256 hashed) PKCE method; the plaintext 'plain' method is rejected because it offers weaker protection.","triggerScenarios":"Sending code_challenge_method=plain (or any value other than S256) alongside a code_challenge on a dynamic client's authorization request.","commonSituations":"Hand-rolled PKCE that defaults to plain; older client libraries defaulting to plain; environment/browser lacking crypto.subtle so code falls back to plain challenge.","solutions":["Generate the challenge as base64url(sha256(verifier)) and send code_challenge_method=S256","Upgrade/replace the client library that defaults to 'plain'","Ensure the page runs in a secure context (https or localhost) so crypto.subtle is available for S256"],"exampleFix":"// before\nconst challenge = base64url(verifier); // plain\n// after\nconst challenge = base64url(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier)));","handlingStrategy":"validation","validationCode":"if (codeChallenge && codeChallengeMethod !== 'S256') {\n  throw new Error('Only S256 PKCE is supported by this server');\n}","typeGuard":"const isS256 = (m?: string): boolean => !m || m === 'S256';","tryCatchPattern":"try { await authorize(req); } catch (e) { if (/S256/.test(e.message)) { codeChallengeMethod = 'S256'; return authorize(req); } throw e; }","preventionTips":["Never default to code_challenge_method=plain","Run PKCE code in secure contexts so crypto.subtle exists"],"tags":["oauth2","pkce","s256","authorization"],"backgroundTag":"oauth-pkce-method-rejected","analyzedSha":"0f1647f7491a217d43eb5ae7a480484bdf0aff3e","analyzedAt":"2026-08-27T12:09:55.020Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}