UNPKG

@auth0/auth0-spa-js

Version:

Auth0 SDK for Single Page Applications using Authorization Code Grant Flow with PKCE

1,134 lines (1,117 loc) 99.7 kB
(function(global, factory) { typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define([ "exports" ], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.auth0 = {})); })(this, (function(exports) { "use strict"; function __rest(s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; } typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {}; function unwrapExports(x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x; } function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var processLock = createCommonjsModule((function(module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); var ProcessLocking = function() { function ProcessLocking() { var _this = this; this.locked = new Map; this.addToLocked = function(key, toAdd) { var callbacks = _this.locked.get(key); if (callbacks === undefined) { if (toAdd === undefined) { _this.locked.set(key, []); } else { _this.locked.set(key, [ toAdd ]); } } else { if (toAdd !== undefined) { callbacks.unshift(toAdd); _this.locked.set(key, callbacks); } } }; this.isLocked = function(key) { return _this.locked.has(key); }; this.lock = function(key) { return new Promise((function(resolve, reject) { if (_this.isLocked(key)) { _this.addToLocked(key, resolve); } else { _this.addToLocked(key); resolve(); } })); }; this.unlock = function(key) { var callbacks = _this.locked.get(key); if (callbacks === undefined || callbacks.length === 0) { _this.locked.delete(key); return; } var toCall = callbacks.pop(); _this.locked.set(key, callbacks); if (toCall !== undefined) { setTimeout(toCall, 0); } }; } ProcessLocking.getInstance = function() { if (ProcessLocking.instance === undefined) { ProcessLocking.instance = new ProcessLocking; } return ProcessLocking.instance; }; return ProcessLocking; }(); function getLock() { return ProcessLocking.getInstance(); } exports.default = getLock; })); unwrapExports(processLock); var browserTabsLock = createCommonjsModule((function(module, exports) { var __awaiter = commonjsGlobal && commonjsGlobal.__awaiter || function(thisArg, _arguments, P, generator) { return new (P || (P = Promise))((function(resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P((function(resolve) { resolve(result.value); })).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); })); }; var __generator = commonjsGlobal && commonjsGlobal.__generator || function(thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), throw: verb(1), return: verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function(v) { return step([ n, v ]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [ op[0] & 2, t.value ]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [ 0 ]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [ 6, e ]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var _this = commonjsGlobal; Object.defineProperty(exports, "__esModule", { value: true }); var LOCK_STORAGE_KEY = "browser-tabs-lock-key"; var DEFAULT_STORAGE_HANDLER = { key: function(index) { return __awaiter(_this, void 0, void 0, (function() { return __generator(this, (function(_a) { throw new Error("Unsupported"); })); })); }, getItem: function(key) { return __awaiter(_this, void 0, void 0, (function() { return __generator(this, (function(_a) { throw new Error("Unsupported"); })); })); }, clear: function() { return __awaiter(_this, void 0, void 0, (function() { return __generator(this, (function(_a) { return [ 2, window.localStorage.clear() ]; })); })); }, removeItem: function(key) { return __awaiter(_this, void 0, void 0, (function() { return __generator(this, (function(_a) { throw new Error("Unsupported"); })); })); }, setItem: function(key, value) { return __awaiter(_this, void 0, void 0, (function() { return __generator(this, (function(_a) { throw new Error("Unsupported"); })); })); }, keySync: function(index) { return window.localStorage.key(index); }, getItemSync: function(key) { return window.localStorage.getItem(key); }, clearSync: function() { return window.localStorage.clear(); }, removeItemSync: function(key) { return window.localStorage.removeItem(key); }, setItemSync: function(key, value) { return window.localStorage.setItem(key, value); } }; function delay(milliseconds) { return new Promise((function(resolve) { return setTimeout(resolve, milliseconds); })); } function generateRandomString(length) { var CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz"; var randomstring = ""; for (var i = 0; i < length; i++) { var INDEX = Math.floor(Math.random() * CHARS.length); randomstring += CHARS[INDEX]; } return randomstring; } function getLockId() { return Date.now().toString() + generateRandomString(15); } var SuperTokensLock = function() { function SuperTokensLock(storageHandler) { this.acquiredIatSet = new Set; this.storageHandler = undefined; this.id = getLockId(); this.acquireLock = this.acquireLock.bind(this); this.releaseLock = this.releaseLock.bind(this); this.releaseLock__private__ = this.releaseLock__private__.bind(this); this.waitForSomethingToChange = this.waitForSomethingToChange.bind(this); this.refreshLockWhileAcquired = this.refreshLockWhileAcquired.bind(this); this.storageHandler = storageHandler; if (SuperTokensLock.waiters === undefined) { SuperTokensLock.waiters = []; } } SuperTokensLock.prototype.acquireLock = function(lockKey, timeout) { if (timeout === void 0) { timeout = 5e3; } return __awaiter(this, void 0, void 0, (function() { var iat, MAX_TIME, STORAGE_KEY, STORAGE, lockObj, TIMEOUT_KEY, lockObjPostDelay, parsedLockObjPostDelay; return __generator(this, (function(_a) { switch (_a.label) { case 0: iat = Date.now() + generateRandomString(4); MAX_TIME = Date.now() + timeout; STORAGE_KEY = LOCK_STORAGE_KEY + "-" + lockKey; STORAGE = this.storageHandler === undefined ? DEFAULT_STORAGE_HANDLER : this.storageHandler; _a.label = 1; case 1: if (!(Date.now() < MAX_TIME)) return [ 3, 8 ]; return [ 4, delay(30) ]; case 2: _a.sent(); lockObj = STORAGE.getItemSync(STORAGE_KEY); if (!(lockObj === null)) return [ 3, 5 ]; TIMEOUT_KEY = this.id + "-" + lockKey + "-" + iat; return [ 4, delay(Math.floor(Math.random() * 25)) ]; case 3: _a.sent(); STORAGE.setItemSync(STORAGE_KEY, JSON.stringify({ id: this.id, iat: iat, timeoutKey: TIMEOUT_KEY, timeAcquired: Date.now(), timeRefreshed: Date.now() })); return [ 4, delay(30) ]; case 4: _a.sent(); lockObjPostDelay = STORAGE.getItemSync(STORAGE_KEY); if (lockObjPostDelay !== null) { parsedLockObjPostDelay = JSON.parse(lockObjPostDelay); if (parsedLockObjPostDelay.id === this.id && parsedLockObjPostDelay.iat === iat) { this.acquiredIatSet.add(iat); this.refreshLockWhileAcquired(STORAGE_KEY, iat); return [ 2, true ]; } } return [ 3, 7 ]; case 5: SuperTokensLock.lockCorrector(this.storageHandler === undefined ? DEFAULT_STORAGE_HANDLER : this.storageHandler); return [ 4, this.waitForSomethingToChange(MAX_TIME) ]; case 6: _a.sent(); _a.label = 7; case 7: iat = Date.now() + generateRandomString(4); return [ 3, 1 ]; case 8: return [ 2, false ]; } })); })); }; SuperTokensLock.prototype.refreshLockWhileAcquired = function(storageKey, iat) { return __awaiter(this, void 0, void 0, (function() { var _this = this; return __generator(this, (function(_a) { setTimeout((function() { return __awaiter(_this, void 0, void 0, (function() { var STORAGE, lockObj, parsedLockObj; return __generator(this, (function(_a) { switch (_a.label) { case 0: return [ 4, processLock.default().lock(iat) ]; case 1: _a.sent(); if (!this.acquiredIatSet.has(iat)) { processLock.default().unlock(iat); return [ 2 ]; } STORAGE = this.storageHandler === undefined ? DEFAULT_STORAGE_HANDLER : this.storageHandler; lockObj = STORAGE.getItemSync(storageKey); if (lockObj !== null) { parsedLockObj = JSON.parse(lockObj); parsedLockObj.timeRefreshed = Date.now(); STORAGE.setItemSync(storageKey, JSON.stringify(parsedLockObj)); processLock.default().unlock(iat); } else { processLock.default().unlock(iat); return [ 2 ]; } this.refreshLockWhileAcquired(storageKey, iat); return [ 2 ]; } })); })); }), 1e3); return [ 2 ]; })); })); }; SuperTokensLock.prototype.waitForSomethingToChange = function(MAX_TIME) { return __awaiter(this, void 0, void 0, (function() { return __generator(this, (function(_a) { switch (_a.label) { case 0: return [ 4, new Promise((function(resolve) { var resolvedCalled = false; var startedAt = Date.now(); var MIN_TIME_TO_WAIT = 50; var removedListeners = false; function stopWaiting() { if (!removedListeners) { window.removeEventListener("storage", stopWaiting); SuperTokensLock.removeFromWaiting(stopWaiting); clearTimeout(timeOutId); removedListeners = true; } if (!resolvedCalled) { resolvedCalled = true; var timeToWait = MIN_TIME_TO_WAIT - (Date.now() - startedAt); if (timeToWait > 0) { setTimeout(resolve, timeToWait); } else { resolve(null); } } } window.addEventListener("storage", stopWaiting); SuperTokensLock.addToWaiting(stopWaiting); var timeOutId = setTimeout(stopWaiting, Math.max(0, MAX_TIME - Date.now())); })) ]; case 1: _a.sent(); return [ 2 ]; } })); })); }; SuperTokensLock.addToWaiting = function(func) { this.removeFromWaiting(func); if (SuperTokensLock.waiters === undefined) { return; } SuperTokensLock.waiters.push(func); }; SuperTokensLock.removeFromWaiting = function(func) { if (SuperTokensLock.waiters === undefined) { return; } SuperTokensLock.waiters = SuperTokensLock.waiters.filter((function(i) { return i !== func; })); }; SuperTokensLock.notifyWaiters = function() { if (SuperTokensLock.waiters === undefined) { return; } var waiters = SuperTokensLock.waiters.slice(); waiters.forEach((function(i) { return i(); })); }; SuperTokensLock.prototype.releaseLock = function(lockKey) { return __awaiter(this, void 0, void 0, (function() { return __generator(this, (function(_a) { switch (_a.label) { case 0: return [ 4, this.releaseLock__private__(lockKey) ]; case 1: return [ 2, _a.sent() ]; } })); })); }; SuperTokensLock.prototype.releaseLock__private__ = function(lockKey) { return __awaiter(this, void 0, void 0, (function() { var STORAGE, STORAGE_KEY, lockObj, parsedlockObj; return __generator(this, (function(_a) { switch (_a.label) { case 0: STORAGE = this.storageHandler === undefined ? DEFAULT_STORAGE_HANDLER : this.storageHandler; STORAGE_KEY = LOCK_STORAGE_KEY + "-" + lockKey; lockObj = STORAGE.getItemSync(STORAGE_KEY); if (lockObj === null) { return [ 2 ]; } parsedlockObj = JSON.parse(lockObj); if (!(parsedlockObj.id === this.id)) return [ 3, 2 ]; return [ 4, processLock.default().lock(parsedlockObj.iat) ]; case 1: _a.sent(); this.acquiredIatSet.delete(parsedlockObj.iat); STORAGE.removeItemSync(STORAGE_KEY); processLock.default().unlock(parsedlockObj.iat); SuperTokensLock.notifyWaiters(); _a.label = 2; case 2: return [ 2 ]; } })); })); }; SuperTokensLock.lockCorrector = function(storageHandler) { var MIN_ALLOWED_TIME = Date.now() - 5e3; var STORAGE = storageHandler; var KEYS = []; var currIndex = 0; while (true) { var key = STORAGE.keySync(currIndex); if (key === null) { break; } KEYS.push(key); currIndex++; } var notifyWaiters = false; for (var i = 0; i < KEYS.length; i++) { var LOCK_KEY = KEYS[i]; if (LOCK_KEY.includes(LOCK_STORAGE_KEY)) { var lockObj = STORAGE.getItemSync(LOCK_KEY); if (lockObj !== null) { var parsedlockObj = JSON.parse(lockObj); if (parsedlockObj.timeRefreshed === undefined && parsedlockObj.timeAcquired < MIN_ALLOWED_TIME || parsedlockObj.timeRefreshed !== undefined && parsedlockObj.timeRefreshed < MIN_ALLOWED_TIME) { STORAGE.removeItemSync(LOCK_KEY); notifyWaiters = true; } } } } if (notifyWaiters) { SuperTokensLock.notifyWaiters(); } }; SuperTokensLock.waiters = undefined; return SuperTokensLock; }(); exports.default = SuperTokensLock; })); var Lock = unwrapExports(browserTabsLock); var version = "2.3.0"; const DEFAULT_AUTHORIZE_TIMEOUT_IN_SECONDS = 60; const DEFAULT_POPUP_CONFIG_OPTIONS = { timeoutInSeconds: DEFAULT_AUTHORIZE_TIMEOUT_IN_SECONDS }; const DEFAULT_SILENT_TOKEN_RETRY_COUNT = 3; const CLEANUP_IFRAME_TIMEOUT_IN_SECONDS = 2; const DEFAULT_FETCH_TIMEOUT_MS = 1e4; const CACHE_LOCATION_MEMORY = "memory"; const MISSING_REFRESH_TOKEN_ERROR_MESSAGE = "Missing Refresh Token"; const INVALID_REFRESH_TOKEN_ERROR_MESSAGE = "invalid refresh token"; const DEFAULT_SCOPE = "openid profile email"; const DEFAULT_SESSION_CHECK_EXPIRY_DAYS = 1; const DEFAULT_AUTH0_CLIENT = { name: "auth0-spa-js", version: version }; const DEFAULT_NOW_PROVIDER = () => Date.now(); class GenericError extends Error { constructor(error, error_description) { super(error_description); this.error = error; this.error_description = error_description; Object.setPrototypeOf(this, GenericError.prototype); } static fromPayload({error: error, error_description: error_description}) { return new GenericError(error, error_description); } } class AuthenticationError extends GenericError { constructor(error, error_description, state, appState = null) { super(error, error_description); this.state = state; this.appState = appState; Object.setPrototypeOf(this, AuthenticationError.prototype); } } class TimeoutError extends GenericError { constructor() { super("timeout", "Timeout"); Object.setPrototypeOf(this, TimeoutError.prototype); } } class PopupTimeoutError extends TimeoutError { constructor(popup) { super(); this.popup = popup; Object.setPrototypeOf(this, PopupTimeoutError.prototype); } } class PopupCancelledError extends GenericError { constructor(popup) { super("cancelled", "Popup closed"); this.popup = popup; Object.setPrototypeOf(this, PopupCancelledError.prototype); } } class MfaRequiredError extends GenericError { constructor(error, error_description, mfa_token) { super(error, error_description); this.mfa_token = mfa_token; Object.setPrototypeOf(this, MfaRequiredError.prototype); } } class MissingRefreshTokenError extends GenericError { constructor(audience, scope) { super("missing_refresh_token", `Missing Refresh Token (audience: '${valueOrEmptyString(audience, [ "default" ])}', scope: '${valueOrEmptyString(scope)}')`); this.audience = audience; this.scope = scope; Object.setPrototypeOf(this, MissingRefreshTokenError.prototype); } } function valueOrEmptyString(value, exclude = []) { return value && !exclude.includes(value) ? value : ""; } const parseAuthenticationResult = queryString => { if (queryString.indexOf("#") > -1) { queryString = queryString.substring(0, queryString.indexOf("#")); } const searchParams = new URLSearchParams(queryString); return { state: searchParams.get("state"), code: searchParams.get("code") || undefined, error: searchParams.get("error") || undefined, error_description: searchParams.get("error_description") || undefined }; }; const runIframe = (authorizeUrl, eventOrigin, timeoutInSeconds = DEFAULT_AUTHORIZE_TIMEOUT_IN_SECONDS) => new Promise(((res, rej) => { const iframe = window.document.createElement("iframe"); iframe.setAttribute("width", "0"); iframe.setAttribute("height", "0"); iframe.style.display = "none"; const removeIframe = () => { if (window.document.body.contains(iframe)) { window.document.body.removeChild(iframe); window.removeEventListener("message", iframeEventHandler, false); } }; let iframeEventHandler; const timeoutSetTimeoutId = setTimeout((() => { rej(new TimeoutError); removeIframe(); }), timeoutInSeconds * 1e3); iframeEventHandler = function(e) { if (e.origin != eventOrigin) return; if (!e.data || e.data.type !== "authorization_response") return; const eventSource = e.source; if (eventSource) { eventSource.close(); } e.data.response.error ? rej(GenericError.fromPayload(e.data.response)) : res(e.data.response); clearTimeout(timeoutSetTimeoutId); window.removeEventListener("message", iframeEventHandler, false); setTimeout(removeIframe, CLEANUP_IFRAME_TIMEOUT_IN_SECONDS * 1e3); }; window.addEventListener("message", iframeEventHandler, false); window.document.body.appendChild(iframe); iframe.setAttribute("src", authorizeUrl); })); const openPopup = url => { const width = 400; const height = 600; const left = window.screenX + (window.innerWidth - width) / 2; const top = window.screenY + (window.innerHeight - height) / 2; return window.open(url, "auth0:authorize:popup", `left=${left},top=${top},width=${width},height=${height},resizable,scrollbars=yes,status=1`); }; const runPopup = config => new Promise(((resolve, reject) => { let popupEventListener; const popupTimer = setInterval((() => { if (config.popup && config.popup.closed) { clearInterval(popupTimer); clearTimeout(timeoutId); window.removeEventListener("message", popupEventListener, false); reject(new PopupCancelledError(config.popup)); } }), 1e3); const timeoutId = setTimeout((() => { clearInterval(popupTimer); reject(new PopupTimeoutError(config.popup)); window.removeEventListener("message", popupEventListener, false); }), (config.timeoutInSeconds || DEFAULT_AUTHORIZE_TIMEOUT_IN_SECONDS) * 1e3); popupEventListener = function(e) { if (!e.data || e.data.type !== "authorization_response") { return; } clearTimeout(timeoutId); clearInterval(popupTimer); window.removeEventListener("message", popupEventListener, false); config.popup.close(); if (e.data.response.error) { return reject(GenericError.fromPayload(e.data.response)); } resolve(e.data.response); }; window.addEventListener("message", popupEventListener); })); const getCrypto = () => window.crypto; const createRandomString = () => { const charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_~."; let random = ""; const randomValues = Array.from(getCrypto().getRandomValues(new Uint8Array(43))); randomValues.forEach((v => random += charset[v % charset.length])); return random; }; const encode = value => btoa(value); const stripUndefined = params => Object.keys(params).filter((k => typeof params[k] !== "undefined")).reduce(((acc, key) => Object.assign(Object.assign({}, acc), { [key]: params[key] })), {}); const createQueryParams = _a => { var {clientId: client_id} = _a, params = __rest(_a, [ "clientId" ]); return new URLSearchParams(stripUndefined(Object.assign({ client_id: client_id }, params))).toString(); }; const sha256 = async s => { const digestOp = getCrypto().subtle.digest({ name: "SHA-256" }, (new TextEncoder).encode(s)); return await digestOp; }; const urlEncodeB64 = input => { const b64Chars = { "+": "-", "/": "_", "=": "" }; return input.replace(/[+/=]/g, (m => b64Chars[m])); }; const decodeB64 = input => decodeURIComponent(atob(input).split("").map((c => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2))).join("")); const urlDecodeB64 = input => decodeB64(input.replace(/_/g, "/").replace(/-/g, "+")); const bufferToBase64UrlEncoded = input => { const ie11SafeInput = new Uint8Array(input); return urlEncodeB64(window.btoa(String.fromCharCode(...Array.from(ie11SafeInput)))); }; const validateCrypto = () => { if (!getCrypto()) { throw new Error("For security reasons, `window.crypto` is required to run `auth0-spa-js`."); } if (typeof getCrypto().subtle === "undefined") { throw new Error(`\n auth0-spa-js must run on a secure origin. See https://github.com/auth0/auth0-spa-js/blob/main/FAQ.md#why-do-i-get-auth0-spa-js-must-run-on-a-secure-origin for more information.\n `); } }; const getDomain = domainUrl => { if (!/^https?:\/\//.test(domainUrl)) { return `https://${domainUrl}`; } return domainUrl; }; const getTokenIssuer = (issuer, domainUrl) => { if (issuer) { return issuer.startsWith("https://") ? issuer : `https://${issuer}/`; } return `${domainUrl}/`; }; const parseNumber = value => { if (typeof value !== "string") { return value; } return parseInt(value, 10) || undefined; }; const sendMessage = (message, to) => new Promise((function(resolve, reject) { const messageChannel = new MessageChannel; messageChannel.port1.onmessage = function(event) { if (event.data.error) { reject(new Error(event.data.error)); } else { resolve(event.data); } messageChannel.port1.close(); }; to.postMessage(message, [ messageChannel.port2 ]); })); const createAbortController = () => new AbortController; const dofetch = async (fetchUrl, fetchOptions) => { const response = await fetch(fetchUrl, fetchOptions); return { ok: response.ok, json: await response.json() }; }; const fetchWithoutWorker = async (fetchUrl, fetchOptions, timeout) => { const controller = createAbortController(); fetchOptions.signal = controller.signal; let timeoutId; return Promise.race([ dofetch(fetchUrl, fetchOptions), new Promise(((_, reject) => { timeoutId = setTimeout((() => { controller.abort(); reject(new Error("Timeout when executing 'fetch'")); }), timeout); })) ]).finally((() => { clearTimeout(timeoutId); })); }; const fetchWithWorker = async (fetchUrl, audience, scope, fetchOptions, timeout, worker, useFormData) => sendMessage({ auth: { audience: audience, scope: scope }, timeout: timeout, fetchUrl: fetchUrl, fetchOptions: fetchOptions, useFormData: useFormData }, worker); const switchFetch = async (fetchUrl, audience, scope, fetchOptions, worker, useFormData, timeout = DEFAULT_FETCH_TIMEOUT_MS) => { if (worker) { return fetchWithWorker(fetchUrl, audience, scope, fetchOptions, timeout, worker, useFormData); } else { return fetchWithoutWorker(fetchUrl, fetchOptions, timeout); } }; async function getJSON(url, timeout, audience, scope, options, worker, useFormData) { let fetchError = null; let response; for (let i = 0; i < DEFAULT_SILENT_TOKEN_RETRY_COUNT; i++) { try { response = await switchFetch(url, audience, scope, options, worker, useFormData, timeout); fetchError = null; break; } catch (e) { fetchError = e; } } if (fetchError) { throw fetchError; } const _a = response.json, {error: error, error_description: error_description} = _a, data = __rest(_a, [ "error", "error_description" ]), {ok: ok} = response; if (!ok) { const errorMessage = error_description || `HTTP error. Unable to fetch ${url}`; if (error === "mfa_required") { throw new MfaRequiredError(error, errorMessage, data.mfa_token); } if (error === "missing_refresh_token") { throw new MissingRefreshTokenError(audience, scope); } throw new GenericError(error || "request_error", errorMessage); } return data; } async function oauthToken(_a, worker) { var {baseUrl: baseUrl, timeout: timeout, audience: audience, scope: scope, auth0Client: auth0Client, useFormData: useFormData} = _a, options = __rest(_a, [ "baseUrl", "timeout", "audience", "scope", "auth0Client", "useFormData" ]); const isTokenExchange = options.grant_type === "urn:ietf:params:oauth:grant-type:token-exchange"; const allParams = Object.assign(Object.assign(Object.assign({}, options), isTokenExchange && audience && { audience: audience }), isTokenExchange && scope && { scope: scope }); const body = useFormData ? createQueryParams(allParams) : JSON.stringify(allParams); return await getJSON(`${baseUrl}/oauth/token`, timeout, audience || "default", scope, { method: "POST", body: body, headers: { "Content-Type": useFormData ? "application/x-www-form-urlencoded" : "application/json", "Auth0-Client": btoa(JSON.stringify(auth0Client || DEFAULT_AUTH0_CLIENT)) } }, worker, useFormData); } const dedupe = arr => Array.from(new Set(arr)); const getUniqueScopes = (...scopes) => dedupe(scopes.filter(Boolean).join(" ").trim().split(/\s+/)).join(" "); const CACHE_KEY_PREFIX = "@@auth0spajs@@"; const CACHE_KEY_ID_TOKEN_SUFFIX = "@@user@@"; class CacheKey { constructor(data, prefix = CACHE_KEY_PREFIX, suffix) { this.prefix = prefix; this.suffix = suffix; this.clientId = data.clientId; this.scope = data.scope; this.audience = data.audience; } toKey() { return [ this.prefix, this.clientId, this.audience, this.scope, this.suffix ].filter(Boolean).join("::"); } static fromKey(key) { const [prefix, clientId, audience, scope] = key.split("::"); return new CacheKey({ clientId: clientId, scope: scope, audience: audience }, prefix); } static fromCacheEntry(entry) { const {scope: scope, audience: audience, client_id: clientId} = entry; return new CacheKey({ scope: scope, audience: audience, clientId: clientId }); } } class LocalStorageCache { set(key, entry) { localStorage.setItem(key, JSON.stringify(entry)); } get(key) { const json = window.localStorage.getItem(key); if (!json) return; try { const payload = JSON.parse(json); return payload; } catch (e) { return; } } remove(key) { localStorage.removeItem(key); } allKeys() { return Object.keys(window.localStorage).filter((key => key.startsWith(CACHE_KEY_PREFIX))); } } class InMemoryCache { constructor() { this.enclosedCache = function() { let cache = {}; return { set(key, entry) { cache[key] = entry; }, get(key) { const cacheEntry = cache[key]; if (!cacheEntry) { return; } return cacheEntry; }, remove(key) { delete cache[key]; }, allKeys() { return Object.keys(cache); } }; }(); } } const DEFAULT_EXPIRY_ADJUSTMENT_SECONDS = 0; class CacheManager { constructor(cache, keyManifest, nowProvider) { this.cache = cache; this.keyManifest = keyManifest; this.nowProvider = nowProvider || DEFAULT_NOW_PROVIDER; } async setIdToken(clientId, idToken, decodedToken) { var _a; const cacheKey = this.getIdTokenCacheKey(clientId); await this.cache.set(cacheKey, { id_token: idToken, decodedToken: decodedToken }); await ((_a = this.keyManifest) === null || _a === void 0 ? void 0 : _a.add(cacheKey)); } async getIdToken(cacheKey) { const entry = await this.cache.get(this.getIdTokenCacheKey(cacheKey.clientId)); if (!entry && cacheKey.scope && cacheKey.audience) { const entryByScope = await this.get(cacheKey); if (!entryByScope) { return; } if (!entryByScope.id_token || !entryByScope.decodedToken) { return; } return { id_token: entryByScope.id_token, decodedToken: entryByScope.decodedToken }; } if (!entry) { return; } return { id_token: entry.id_token, decodedToken: entry.decodedToken }; } async get(cacheKey, expiryAdjustmentSeconds = DEFAULT_EXPIRY_ADJUSTMENT_SECONDS) { var _a; let wrappedEntry = await this.cache.get(cacheKey.toKey()); if (!wrappedEntry) { const keys = await this.getCacheKeys(); if (!keys) return; const matchedKey = this.matchExistingCacheKey(cacheKey, keys); if (matchedKey) { wrappedEntry = await this.cache.get(matchedKey); } } if (!wrappedEntry) { return; } const now = await this.nowProvider(); const nowSeconds = Math.floor(now / 1e3); if (wrappedEntry.expiresAt - expiryAdjustmentSeconds < nowSeconds) { if (wrappedEntry.body.refresh_token) { wrappedEntry.body = { refresh_token: wrappedEntry.body.refresh_token }; await this.cache.set(cacheKey.toKey(), wrappedEntry); return wrappedEntry.body; } await this.cache.remove(cacheKey.toKey()); await ((_a = this.keyManifest) === null || _a === void 0 ? void 0 : _a.remove(cacheKey.toKey())); return; } return wrappedEntry.body; } async set(entry) { var _a; const cacheKey = new CacheKey({ clientId: entry.client_id, scope: entry.scope, audience: entry.audience }); const wrappedEntry = await this.wrapCacheEntry(entry); await this.cache.set(cacheKey.toKey(), wrappedEntry); await ((_a = this.keyManifest) === null || _a === void 0 ? void 0 : _a.add(cacheKey.toKey())); } async clear(clientId) { var _a; const keys = await this.getCacheKeys(); if (!keys) return; await keys.filter((key => clientId ? key.includes(clientId) : true)).reduce((async (memo, key) => { await memo; await this.cache.remove(key); }), Promise.resolve()); await ((_a = this.keyManifest) === null || _a === void 0 ? void 0 : _a.clear()); } async wrapCacheEntry(entry) { const now = await this.nowProvider(); const expiresInTime = Math.floor(now / 1e3) + entry.expires_in; return { body: entry, expiresAt: expiresInTime }; } async getCacheKeys() { var _a; if (this.keyManifest) { return (_a = await this.keyManifest.get()) === null || _a === void 0 ? void 0 : _a.keys; } else if (this.cache.allKeys) { return this.cache.allKeys(); } } getIdTokenCacheKey(clientId) { return new CacheKey({ clientId: clientId }, CACHE_KEY_PREFIX, CACHE_KEY_ID_TOKEN_SUFFIX).toKey(); } matchExistingCacheKey(keyToMatch, allKeys) { return allKeys.filter((key => { var _a; const cacheKey = CacheKey.fromKey(key); const scopeSet = new Set(cacheKey.scope && cacheKey.scope.split(" ")); const scopesToMatch = ((_a = keyToMatch.scope) === null || _a === void 0 ? void 0 : _a.split(" ")) || []; const hasAllScopes = cacheKey.scope && scopesToMatch.reduce(((acc, current) => acc && scopeSet.has(current)), true); return cacheKey.prefix === CACHE_KEY_PREFIX && cacheKey.clientId === keyToMatch.clientId && cacheKey.audience === keyToMatch.audience && hasAllScopes; }))[0]; } } const TRANSACTION_STORAGE_KEY_PREFIX = "a0.spajs.txs"; class TransactionManager { constructor(storage, clientId, cookieDomain) { this.storage = storage; this.clientId = clientId; this.cookieDomain = cookieDomain; this.storageKey = `${TRANSACTION_STORAGE_KEY_PREFIX}.${this.clientId}`; } create(transaction) { this.storage.save(this.storageKey, transaction, { daysUntilExpire: 1, cookieDomain: this.cookieDomain }); } get() { return this.storage.get(this.storageKey); } remove() { this.storage.remove(this.storageKey, { cookieDomain: this.cookieDomain }); } } const isNumber = n => typeof n === "number"; const idTokendecoded = [ "iss", "aud", "exp", "nbf", "iat", "jti", "azp", "nonce", "auth_time", "at_hash", "c_hash", "acr", "amr", "sub_jwk", "cnf", "sip_from_tag", "sip_date", "sip_callid", "sip_cseq_num", "sip_via_branch", "orig", "dest", "mky", "events", "toe", "txn", "rph", "sid", "vot", "vtm" ]; const decode = token => { const parts = token.split("."); const [header, payload, signature] = parts; if (parts.length !== 3 || !header || !payload || !signature) { throw new Error("ID token could not be decoded"); } const payloadJSON = JSON.parse(urlDecodeB64(payload)); const claims = { __raw: token }; const user = {}; Object.keys(payloadJSON).forEach((k => { claims[k] = payloadJSON[k]; if (!idTokendecoded.includes(k)) { user[k] = payloadJSON[k]; } })); return { encoded: { header: header, payload: payload, signature: signature }, header: JSON.parse(urlDecodeB64(header)), claims: claims, user: user }; }; const verify = options => { if (!options.id_token) { throw new Error("ID token is required but missing"); } const decoded = decode(options.id_token); if (!decoded.claims.iss) { throw new Error("Issuer (iss) claim must be a string present in the ID token"); } if (decoded.claims.iss !== options.iss) { throw new Error(`Issuer (iss) claim mismatch in the ID token; expected "${options.iss}", found "${decoded.claims.iss}"`); } if (!decoded.user.sub) { throw new Error("Subject (sub) claim must be a string present in the ID token"); } if (decoded.header.alg !== "RS256") { throw new Error(`Signature algorithm of "${decoded.header.alg}" is not supported. Expected the ID token to be signed with "RS256".`); } if (!decoded.claims.aud || !(typeof decoded.claims.aud === "string" || Array.isArray(decoded.claims.aud))) { throw new Error("Audience (aud) claim must be a string or array of strings present in the ID token"); } if (Array.isArray(decoded.claims.aud)) { if (!decoded.claims.aud.includes(options.aud)) { throw new Error(`Audience (aud) claim mismatch in the ID token; expected "${options.aud}" but was not on