"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createRemoteJWKSet = void 0; const fetch_jwks_js_1 = require("../runtime/fetch_jwks.js"); const errors_js_1 = require("../util/errors.js"); const local_js_1 = require("./local.js"); function isCloudflareWorkers() { return (typeof WebSocketPair !== 'undefined' || (typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Workers') || (typeof EdgeRuntime !== 'undefined' && EdgeRuntime === 'vercel')); } let USER_AGENT; if (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) { const NAME = 'jose'; const VERSION = 'v5.2.2'; USER_AGENT = `${NAME}/${VERSION}`; } class RemoteJWKSet extends local_js_1.LocalJWKSet { _url; _timeoutDuration; _cooldownDuration; _cacheMaxAge; _jwksTimestamp; _pendingFetch; _options; constructor(url, options) { super({ keys: [] }); this._jwks = undefined; if (!(url instanceof URL)) { throw new TypeError('url must be an instance of URL'); } this._url = new URL(url.href); this._options = { agent: options?.agent, headers: options?.headers }; this._timeoutDuration = typeof options?.timeoutDuration === 'number' ? options?.timeoutDuration : 5000; this._cooldownDuration = typeof options?.cooldownDuration === 'number' ? options?.cooldownDuration : 30000; this._cacheMaxAge = typeof options?.cacheMaxAge === 'number' ? options?.cacheMaxAge : 600000; } coolingDown() { return typeof this._jwksTimestamp === 'number' ? Date.now() < this._jwksTimestamp + this._cooldownDuration : false; } fresh() { return typeof this._jwksTimestamp === 'number' ? Date.now() < this._jwksTimestamp + this._cacheMaxAge : false; } async getKey(protectedHeader, token) { if (!this._jwks || !this.fresh()) { await this.reload(); } try { return await super.getKey(protectedHeader, token); } catch (err) { if (err instanceof errors_js_1.JWKSNoMatchingKey) { if (this.coolingDown() === false) { await this.reload(); return super.getKey(protectedHeader, token); } } throw err; } } async reload() { if (this._pendingFetch && isCloudflareWorkers()) { this._pendingFetch = undefined; } const headers = new Headers(this._options.headers); if (USER_AGENT && !headers.has('User-Agent')) { headers.set('User-Agent', USER_AGENT); this._options.headers = Object.fromEntries(headers.entries()); } this._pendingFetch ||= (0, fetch_jwks_js_1.default)(this._url, this._timeoutDuration, this._options) .then((json) => { if (!(0, local_js_1.isJWKSLike)(json)) { throw new errors_js_1.JWKSInvalid('JSON Web Key Set malformed'); } this._jwks = { keys: json.keys }; this._jwksTimestamp = Date.now(); this._pendingFetch = undefined; }) .catch((err) => { this._pendingFetch = undefined; throw err; }); await this._pendingFetch; } } function createRemoteJWKSet(url, options) { const set = new RemoteJWKSet(url, options); return async (protectedHeader, token) => set.getKey(protectedHeader, token); } exports.createRemoteJWKSet = createRemoteJWKSet;