UNPKG

firebase-auth-cloudflare-workers

Version:

Zero-dependencies firebase auth library for Cloudflare Workers.

82 lines (81 loc) 3.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EmulatorSignatureVerifier = exports.PublicKeySignatureVerifier = exports.rs256alg = void 0; const errors_1 = require("./errors"); const jwk_fetcher_1 = require("./jwk-fetcher"); const validator_1 = require("./validator"); // https://firebase.google.com/docs/auth/admin/verify-id-tokens#verify_id_tokens_using_a_third-party_jwt_library // https://developer.mozilla.org/en-US/docs/Web/API/RsaHashedKeyGenParams exports.rs256alg = { name: 'RSASSA-PKCS1-v1_5', modulusLength: 2048, publicExponent: new Uint8Array([0x01, 0x00, 0x01]), hash: 'SHA-256', }; /** * Class for verifying JWT signature with a public key. */ class PublicKeySignatureVerifier { keyFetcher; constructor(keyFetcher) { this.keyFetcher = keyFetcher; if (!(0, validator_1.isNonNullObject)(keyFetcher)) { throw new Error('The provided key fetcher is not an object or null.'); } } static withCertificateUrl(clientCertUrl, keyStorer) { const fetcher = new jwk_fetcher_1.HTTPFetcher(clientCertUrl); return new PublicKeySignatureVerifier(new jwk_fetcher_1.UrlKeyFetcher(fetcher, keyStorer)); } /** * Verifies the signature of a JWT using the provided secret or a function to fetch * the public key. * * @param token - The JWT to be verified. * @throws If the JWT is not a valid RS256 token. * @returns A Promise resolving for a token with a valid signature. */ async verify(token) { const { header } = token.decodedToken; const publicKeys = await this.fetchPublicKeys(); for (const publicKey of publicKeys) { if (publicKey.kid !== header.kid) { continue; } const verified = await this.verifySignature(token, publicKey); if (verified) { // succeeded return; } throw new errors_1.JwtError(errors_1.JwtErrorCode.INVALID_SIGNATURE, 'The token signature is invalid.'); } throw new errors_1.JwtError(errors_1.JwtErrorCode.NO_MATCHING_KID, 'The token does not match the kid.'); } async verifySignature(token, publicJWK) { try { const key = await crypto.subtle.importKey('jwk', publicJWK, exports.rs256alg, false, ['verify']); return await crypto.subtle.verify(exports.rs256alg, key, token.decodedToken.signature, token.getHeaderPayloadBytes()); } catch (err) { throw new errors_1.JwtError(errors_1.JwtErrorCode.INVALID_SIGNATURE, `Error verifying signature: ${err}`); } } async fetchPublicKeys() { try { return await this.keyFetcher.fetchPublicKeys(); } catch (err) { throw new errors_1.JwtError(errors_1.JwtErrorCode.KEY_FETCH_ERROR, `Error fetching public keys for Google certs: ${err}`); } } } exports.PublicKeySignatureVerifier = PublicKeySignatureVerifier; /** * Class for verifying unsigned (emulator) JWTs. */ class EmulatorSignatureVerifier { async verify() { // Signature checks skipped for emulator; no need to fetch public keys. } } exports.EmulatorSignatureVerifier = EmulatorSignatureVerifier;