We’ve been pushing hard to get our internal dashboard running on the Genesys Cloud implicit grant flow, but I’m hitting a wall when trying to validate the returned JWTs on the client side. The setup is pretty standard React with create-react-app, and we’re using the @genesys/cloud-auth library to handle the initial redirect and token exchange. The auth part works fine; I get the id_token and access_token in the URL hash after the user logs in.
The problem is that the React app needs to verify the token’s integrity before making any API calls to /api/v2/user/me. I can’t send the token to a backend for validation because this is a purely static site hosted on S3. I tried using the jwt-decode library, but it’s just parsing the JSON without checking the signature, which feels insecure.
I found the public keys at https://login.mypurecloud.com/keys, but the response is a JWK set, not a simple PEM string. I’ve been trying to convert the JWK to a usable format using jose or node-jose, but I keep running into issues with the alg header matching. The token has alg: RS256, and the JWK has kty: RSA.
Here’s the snippet I’m wrestling with:
import { importJWK, verify } from 'jose';
async function validateToken(token) {
const [header, payload, signature] = token.split('.');
const jwks = await fetch('https://login.mypurecloud.com/keys');
const keys = await jwks.json();
// This part is messy
const key = keys.keys.find(k => k.kid === header.kid);
const publicKey = await importJWK(key, 'RS256');
// This throws "invalid signature"
const { protectedHeader, payload: decodedPayload } = await verify(token, publicKey);
return decodedPayload;
}
The verify call consistently fails with an “invalid signature” error, even though the token was just issued. I suspect I’m importing the JWK incorrectly or missing a step in the key conversion. Has anyone successfully validated Genesys JWTs in a browser-only environment? The docs are surprisingly silent on this specific client-side validation pattern.