Validating Genesys Cloud implicit grant JWT in React fails on signature check

We’re building a simple React dashboard that pulls some user data from Genesys Cloud. Since we’re doing an SPA, we’re using the implicit grant flow to get the tokens. The login works fine and I get the ID token back in the URL fragment after redirect.

The problem is validating that token on the client side before I make any API calls. I’m using jwt-decode to parse it, but I also want to verify the signature so we aren’t just trusting whatever is in the URL. I found the JWKS endpoint at https://api.mypurecloud.com/oauth2/jwks and I’m fetching the keys there.

Here is the rough validation logic I’ve thrown together:

import jwt from 'jsonwebtoken';

const validateToken = async (idToken) => {
 const response = await fetch('https://api.mypurecloud.com/oauth2/jwks');
 const keys = await response.json();
 
 // Find the matching key by kid
 const header = jwt.decode(idToken, { complete: true });
 const kid = header.header.kid;
 const jwk = keys.keys.find(k => k.kid === kid);
 
 // Convert JWK to PEM
 const publicKey = jwkToPem(jwk); 

 try {
 jwt.verify(idToken, publicKey, { algorithms: ['RS256'] });
 return true;
 } catch (err) {
 console.error('Token invalid:', err);
 return false;
 }
};

The jwt.verify call always throws JsonWebTokenError: invalid signature. I’ve checked the kid and it matches one of the keys in the JWKS response. The alg in the header is RS256. I’m using a standard jwk-to-pem converter for the key transformation.

Is there something specific about the Genesys Cloud JWKS format I’m missing? Or is this whole approach flawed for an implicit grant in a browser environment? I don’t want to hit the /api/v2/users/me endpoint just to validate the token if I can avoid it, feels wasteful.

Any pointers on getting the signature check to pass?