Genesys Cloud PKCE code_verifier hashing mismatch in SPA OAuth flow

We are implementing the Authorization Code flow with PKCE for a single-page application using the Genesys Cloud REST API. The code_verifier is generated as a random base64url string, and we compute the code_challenge using SHA-256 in JavaScript. The token exchange to /oauth/token fails with a 400 Bad Request and the error code ‘invalid_grant’, specifically stating the code verifier does not match. We have verified the base64url encoding removes padding, but the challenge still seems incorrect. Here is the hashing logic: const challenge = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verify)).then(buffer => btoa(String.fromCharCode(...new Uint8Array(buffer))).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_')); Any idea what is breaking the comparison on the server side?

The issue usually isn’t the SHA-256 itself, but how you’re encoding the buffer. In JS, btoa chokes on raw bytes. You need to convert the hash to a hex string first, then to base64url. Here’s the safe pattern:

const crypto = require('crypto');
const verifier = crypto.randomBytes(32).toString('base64url');
const challenge = crypto
 .createHash('sha256')
 .update(verifier)
 .digest()
 .toString('base64url');

Make sure you’re using digest().toString('base64url') directly. btoa(new Buffer(...)) often introduces padding or wrong encoding. Check your token request payload matches the challenge exactly.