Skip to content

Instantly share code, notes, and snippets.

@congnd
Created October 6, 2023 10:02

Revisions

  1. congnd created this gist Oct 6, 2023.
    52 changes: 52 additions & 0 deletions jwtverify.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,52 @@
    // 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