@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
JavaScript
(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