frontend/app/JwtHelpers.jsx (69 lines of code) (raw):

import * as jose from 'jose'; async function checkToken(token, keyURL) { const JWKS = jose.createRemoteJWKSet(new URL(keyURL)); const { payload, protectedHeader } = await jose .jwtVerify(token, JWKS) .catch(async (error) => { if (error?.code === 'ERR_JWKS_MULTIPLE_MATCHING_KEYS') { for await (const publicKey of error) { console.log("publicKey: " + publicKey); try { return await jose.jwtVerify(token, publicKey, options) } catch (innerError) { if (innerError?.code === 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED') { continue } throw innerError } } throw new jose.errors.JWSSignatureVerificationFailed() } throw error }) } /** * Perform the validation of the token via jose library. * If validation fails then the returned promise is rejected. * If validation succeeds, then the promise only completes once the decoded content has been set into the state. * @returns {Promise<object>} Decoded JWT content or rejects with an error */ function validateAndDecode(token, signingKey, keyURL, refreshToken) { return new Promise((resolve, reject) => { try { const {payload, protectedHeader} = checkToken(token, keyURL); window.localStorage.setItem("fibrecensus:access-token", token); //It validates so, save the token if (refreshToken) window.localStorage.setItem("fibrecensus:refresh-token", refreshToken); resolve(payload); } catch (err) { console.log("Token: ", token); console.error("Could not verify JWT: ", err); reject(err) } }); } /** * gets the signing key from the server * @returns {Promise<string>} Raw content of the signing key in PEM format */ async function loadInSigningKey() { const result = await fetch("/meta/oauth/publickey.pem"); switch (result.status) { case 200: return result.text(); default: console.error( "could not retrieve signing key, server gave us ", result.status ); throw "Could not retrieve signing key"; } } /** * returns the raw JWT for passing to backend services * @returns {string} the JWT, or null if it is not set. */ function getRawToken() { return window.localStorage.getItem("fibrecensus:access-token"); } export { validateAndDecode, loadInSigningKey, getRawToken };