On This Page
JWT Validation Keys
Unified Click to Pay
uses JWTs to transfer data. These Unified Click to Pay
integration elements are JWTs:- The capture context that is returned by the/uctp/v1/sessionsrequest. You must verify this JWT immediately on your server to ensure that the SDK script URL, PAN encryption keys, and session configuration have not been tampered with.For information about/uctp/v1/sessionsrequests, see Generate Unified Click to Pay Capture Context in theCybersourceAPI Reference.
- The response that is returned bycheckout(). You must verify this JWT on your server after you receive it from the client.
IMPORTANT
The header of each JWT header contains a key ID field
(
kid
) that references the specific RSA public key that
Cybersource
used to sign that token. The integrator must
retrieve this public key from Cybersource
and use it to verify
the JWT's signature. If the signature is invalid, the JWT must be
rejected.JWT validation keys are composed of these elements located in the JWT header:
- kid: Key ID that references the RSA public key that signed the JWT. Each JWT may have a differentkid.
- alg: The signing algorithm. This is oftenRS256(RSA with SHA-256).
You can retrieve the RSA public key as a JSON Web Key from these endpoints:
- Test: GEThttps://apitest.cybersource.com/flex/v2/public-keys/{kid}
- Production: GEThttps://api.cybersource.com/flex/v2/public-keys/{kid}
IMPORTANT
You can store RSA public keys, however,
Cybersource
recommends that you use the keys from the URL. This
ensures that you use the most current key.JavaScript Example: JWT Signature Authentication
async function verifyJwt(token) { const [headerB64, payloadB64, signatureB64] = token.split('.'); const header = JSON.parse(base64UrlDecode(headerB64)); // Fetch the public key using the kid from the JWT header const response = await fetch(`https://${API_HOST}/flex/v2/public-keys/${header.kid}`, { headers: generateSignatureHeaders('GET', `/flex/v2/public-keys/${header.kid}`, null) }); const jwk = await response.json(); const publicKey = crypto.createPublicKey({ key: jwk, format: 'jwk' }); // Verify the signature const signedData = `${headerB64}.${payloadB64}`; const signatureBuffer = base64UrlDecode(signatureB64); const valid = crypto.verify('RSA-SHA256', Buffer.from(signedData), publicKey, signatureBuffer); if (!valid) throw new Error('JWT signature verification failed'); return { header, payload: JSON.parse(base64UrlDecode(payloadB64)), signature: signatureB64, raw: token }; }