Skip to content

Instantly share code, notes, and snippets.

@congnd
Created October 6, 2023 10:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save congnd/e685648221912d6c8df67e58de10fc7c to your computer and use it in GitHub Desktop.
Save congnd/e685648221912d6c8df67e58de10fc7c to your computer and use it in GitHub Desktop.
Pure JS implementation for verifying Firebase Authentication's JWTs, this can be used on CloudFlare where NodeJS runtime is not fully supported
// refs:
// 1. https://stackoverflow.com/questions/71638739/validating-firebase-auth-tokens-manually
// 2. https://gist.github.com/bcnzer/e6a7265fd368fa22ef960b17b9a76488
// Once it is verified, you should check the payload as described in the Firebase doc:
// https://firebase.google.com/docs/auth/admin/verify-id-tokens#verify_id_tokens_using_a_third-party_jwt_library
async function verify(token) {
const decodedToken = decodeJwt(token)
console.log(JSON.stringify(decodedToken));
const jwk = await fetchPublicKey(decodedToken.header.kid)
console.log(jwk);
const encoder = new TextEncoder();
const data = encoder.encode([decodedToken.raw.header, decodedToken.raw.payload].join("."));
const signature = new Uint8Array(
Array.from(decodedToken.signature).map((c) => c.charCodeAt(0))
);
const key = await crypto.subtle.importKey(
"jwk",
jwk,
{ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
false,
["verify"]
);
return crypto.subtle.verify("RSASSA-PKCS1-v1_5", key, signature, data);
}
async function fetchPublicKey(kid) {
const result = await (
await fetch(
"https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com"
)
).json();
return result.keys.find((key) => key.kid === kid);
}
function decodeJwt(token) {
const parts = token.split('.');
const header = JSON.parse(atob(parts[0]));
const payload = JSON.parse(atob(parts[1]));
const signature = atob(parts[2].replace(/_/g, '/').replace(/-/g, '+'));
return {
header: header,
payload: payload,
signature: signature,
raw: { header: parts[0], payload: parts[1], signature: parts[2] }
}
}
export default verify
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment