UNPKG

@pushforge/builder

Version:

A robust, cross-platform Web Push notification library that handles VAPID authentication and payload encryption following the Web Push Protocol standard. Works in Node.js 16+, Browsers, Deno, Bun and Cloudflare Workers.

55 lines (54 loc) 2.57 kB
import { base64UrlEncode } from './base64.js'; import { crypto } from './crypto.js'; import { createJwt } from './jwt.js'; import { getPublicKeyFromJwk } from './utils.js'; /** * Constructs the VAPID headers for a push notification request. * * This function generates the necessary headers for sending a push notification * using the VAPID protocol, including authentication and encryption information. * * @param {PushOptions} options - The options for the push notification, including the JSON Web Key (JWK) and JWT data. * @param {number} payloadLength - The length of the payload being sent in the push notification. * @param {Uint8Array} salt - A salt value used in the encryption process. * @param {CryptoKey} localPublicKey - The local public key used for encryption. * @returns {Promise<Record<string, string> | Headers>} A promise that resolves to an object containing the VAPID headers. * * @throws {Error} Throws an error if the JWT creation fails or if key export fails. */ export const vapidHeaders = async (options, payloadLength, salt, localPublicKey) => { // Export the local public key to a raw format and encode it in Base64 URL format const localPublicKeyBase64 = await crypto.subtle .exportKey('raw', localPublicKey) .then((bytes) => base64UrlEncode(bytes)); // Get the server public key from the JWK const serverPublicKey = getPublicKeyFromJwk(options.jwk); // Create the JWT for authentication const jwt = await createJwt(options.jwk, options.jwt); // Construct the header values for the VAPID request const headerValues = { Encryption: `salt=${base64UrlEncode(salt)}`, 'Crypto-Key': `dh=${localPublicKeyBase64}`, 'Content-Length': payloadLength.toString(), 'Content-Type': 'application/octet-stream', 'Content-Encoding': 'aesgcm', Authorization: `vapid t=${jwt}, k=${serverPublicKey}`, }; let headers; // Add optional headers if they are defined if (options.ttl !== undefined) headerValues.TTL = options.ttl.toString(); if (options.topic !== undefined) headerValues.Topic = options.topic; if (options.urgency !== undefined) headerValues.Urgency = options.urgency; // Create Headers object if available (for browser or Node.js 18+) if (typeof Headers !== 'undefined') { headers = new Headers(headerValues); } else { // Fallback for Node.js < 18 without polyfill headers = headerValues; } return headers; // Return the constructed headers };