Validating implicit grant JWTs in React custom desktop app returns invalid signature

I’m hitting a wall trying to validate the JWT token returned from the Genesys Cloud implicit grant flow inside a React custom agent desktop app. The token comes back fine, and I can decode it with jwt-decode, but when I try to verify the signature using the public keys from the JWKS endpoint, it always fails with an ‘invalid signature’ error. This is happening even though the token was just issued and hasn’t expired. It’s not a clock skew issue since the exp claim is clearly in the future. I’m building a custom screen pop component that needs to authenticate requests to our internal backend, so I can’t just pass the token as-is without verifying it first. The backend rejects it because it can’t validate the signature against the Genesys Cloud public keys. I’ve tried fetching the keys from https://api.mypurecloud.com/oauth2/v2/keys and using jose library in Node/React, but nothing sticks. The header says alg: RS256, and I’m grabbing the key with the matching kid, but the verification step throws. Here’s the snippet I’m using for verification:

const verifyToken = async (token) => {
 const response = await fetch('https://api.mypurecloud.com/oauth2/v2/keys');
 const jwks = await response.json();
 const header = jwtDecode(token, { header: true });
 const key = jwks.keys.find(k => k.kid === header.kid);
 const publicKey = importSPKI(key.n, key.e); // simplified
 return jwtVerify(token, publicKey);
};

The environment details are:

  • Genesys Cloud EU region
  • Implicit grant flow (no PKCE, legacy requirement for this specific desktop widget)
  • React 18 with Vite
  • jose v4.14.0 for crypto operations
  • Token audience (aud) matches the application ID in the portal

I’ve checked the jwks_uri in the .well-known/openid-configuration endpoint, and it points to the same keys endpoint. I’m wondering if there’s a specific claim or header I’m missing, or if the implicit grant tokens use a different signing mechanism than the standard OAuth2 tokens. The logs show the kid matches, but the crypto operation fails silently or throws a generic error. I’ve also tried using jsonwebtoken package with the PEM string conversion, but it behaves the same. No clear error message from Genesys side, just the crypto library failing. I’m stuck on why the signature won’t validate locally when the token is clearly valid for API calls.