UNPKG

@hellocoop/email-verification

Version:

Functions for generating and verifying JWT tokens used in the Email Verification Protocol

116 lines 4.84 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.generateRequestToken = generateRequestToken; exports.verifyRequestToken = verifyRequestToken; const jose_1 = require("jose"); const crypto_js_1 = require("../utils/crypto.js"); const time_js_1 = require("../utils/time.js"); const validation_js_1 = require("../utils/validation.js"); const errors_js_1 = require("../errors.js"); /** * Generates a RequestToken (JWT) for requesting verified email tokens from issuers * Used by browsers in step 3.4 of the email-verification protocol * * @param payload - RequestToken payload containing aud, nonce, email, and optional iss, iat * @param jwk - JWK containing private key, alg, and kid * @param options - Optional token generation options * @returns Promise resolving to signed JWT string */ async function generateRequestToken(payload, jwk, options) { // Validate the JWK (0, crypto_js_1.validateJWK)(jwk); // Validate email format (0, validation_js_1.validateEmailClaim)(payload); // Ensure iat is set (current time if not provided) const payloadWithIat = (0, time_js_1.ensureIatClaim)(payload); // Extract algorithm from JWK const algorithm = options?.algorithm || jwk.alg; if (!algorithm) { throw new Error('Algorithm must be specified in JWK or options'); } // Import the private key const privateKey = await (0, jose_1.importJWK)(jwk, algorithm); // Extract public key parameters for header const publicKeyForHeader = (0, crypto_js_1.extractPublicKeyParameters)(jwk); // Create and sign the JWT const jwt = await new jose_1.SignJWT(payloadWithIat) .setProtectedHeader({ alg: algorithm, typ: 'JWT', jwk: publicKeyForHeader, kid: jwk.kid, }) .sign(privateKey); return jwt; } /** * Verifies a RequestToken (JWT) from browsers * Used by issuers in step 4.1 of the email-verification protocol * * @param token - JWT string to verify * @returns Promise resolving to verified payload */ async function verifyRequestToken(token) { // Parse the JWT const { header, payload } = (0, validation_js_1.parseJWT)(token); // Validate required header fields if (!header.jwk) { throw new errors_js_1.InvalidSignatureError('RequestToken header must contain embedded public key (jwk)'); } if (!header.alg) { throw new errors_js_1.InvalidSignatureError('RequestToken header must contain algorithm (alg)'); } // Validate required payload claims (0, validation_js_1.validateRequiredClaims)(payload, ['aud', 'nonce', 'email']); // Validate email format (0, validation_js_1.validateEmailClaim)(payload); // Validate iat claim (0, time_js_1.validateIatForVerification)(payload.iat); // Import the public key from header const publicKey = await (0, jose_1.importJWK)(header.jwk, header.alg); // Verify the JWT signature using jose's jwtVerify try { const { jwtVerify } = await Promise.resolve().then(() => __importStar(require('jose'))); const { payload: verifiedPayload } = await jwtVerify(token, publicKey, { algorithms: [header.alg], }); return verifiedPayload; } catch (error) { throw new errors_js_1.InvalidSignatureError(`RequestToken signature verification failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } } //# sourceMappingURL=request-token.js.map