@upbond/customauth
Version:
CustomAuth login with torus to get user private key
1,437 lines (1,355 loc) • 72.8 kB
JavaScript
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ // The require scope
/******/ var __webpack_require__ = {};
/******/
/************************************************************************/
/******/ /* webpack/runtime/compat get default export */
/******/ (() => {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = (module) => {
/******/ var getter = module && module.__esModule ?
/******/ () => (module['default']) :
/******/ () => (module);
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// ESM COMPAT FLAG
__webpack_require__.r(__webpack_exports__);
// EXPORTS
__webpack_require__.d(__webpack_exports__, {
AGGREGATE_VERIFIER: () => (/* reexport */ AGGREGATE_VERIFIER),
LOGIN: () => (/* reexport */ LOGIN),
REDIRECT_PARAMS_STORAGE_METHOD: () => (/* reexport */ REDIRECT_PARAMS_STORAGE_METHOD),
SENTRY_TXNS: () => (/* reexport */ SENTRY_TXNS),
TORUS_METHOD: () => (/* reexport */ TORUS_METHOD),
UX_MODE: () => (/* reexport */ UX_MODE),
are3PCSupported: () => (/* reexport */ are3PCSupported),
broadcastChannelOptions: () => (/* reexport */ broadcastChannelOptions),
constructURL: () => (/* reexport */ constructURL),
createHandler: () => (/* reexport */ HandlerFactory),
"default": () => (/* reexport */ login),
eventToPromise: () => (/* reexport */ eventToPromise),
getPopupFeatures: () => (/* reexport */ getPopupFeatures),
getVerifierId: () => (/* reexport */ getVerifierId),
handleRedirectParameters: () => (/* reexport */ handleRedirectParameters),
isFirefox: () => (/* reexport */ isFirefox),
loginToConnectionMap: () => (/* reexport */ loginToConnectionMap),
padUrlString: () => (/* reexport */ padUrlString),
randomId: () => (/* reexport */ randomId),
storageAvailable: () => (/* reexport */ storageAvailable),
validateAndConstructUrl: () => (/* reexport */ validateAndConstructUrl)
});
;// CONCATENATED MODULE: ./src/utils/enums.ts
const LOGIN = {
GOOGLE: "google",
FACEBOOK: "facebook",
REDDIT: "reddit",
DISCORD: "discord",
TWITCH: "twitch",
APPLE: "apple",
GITHUB: "github",
LINKEDIN: "linkedin",
TWITTER: "twitter",
WEIBO: "weibo",
LINE: "line",
EMAIL_PASSWORD: "email_password",
PASSWORDLESS: "passwordless",
JWT: "jwt",
WEBAUTHN: "webauthn"
};
const AGGREGATE_VERIFIER = {
SINGLE_VERIFIER_ID: "single_id_verifier"
// AND_AGGREGATE_VERIFIER : "and_aggregate_verifier",
// OR_AGGREGATE_VERIFIER : "or_aggregate_verifier",
};
const UX_MODE = {
POPUP: "popup",
REDIRECT: "redirect"
};
const REDIRECT_PARAMS_STORAGE_METHOD = {
LOCAL_STORAGE: "localStorage",
SESSION_STORAGE: "sessionStorage",
SERVER: "server"
};
const TORUS_METHOD = {
TRIGGER_LOGIN: "triggerLogin",
TRIGGER_AGGREGATE_LOGIN: "triggerAggregateLogin",
TRIGGER_AGGREGATE_HYBRID_LOGIN: "triggerHybridAggregateLogin"
};
const SENTRY_TXNS = {
FETCH_NODE_DETAILS: "fetchNodeDetails",
PUB_ADDRESS_LOOKUP: "pubAddressLookup",
FETCH_SHARES: "fetchShares"
};
;// CONCATENATED MODULE: external "@babel/runtime/helpers/defineProperty"
const defineProperty_namespaceObject = require("@babel/runtime/helpers/defineProperty");
var defineProperty_default = /*#__PURE__*/__webpack_require__.n(defineProperty_namespaceObject);
;// CONCATENATED MODULE: external "@toruslabs/http-helpers"
const http_helpers_namespaceObject = require("@toruslabs/http-helpers");
;// CONCATENATED MODULE: external "lodash.merge"
const external_lodash_merge_namespaceObject = require("lodash.merge");
var external_lodash_merge_default = /*#__PURE__*/__webpack_require__.n(external_lodash_merge_namespaceObject);
;// CONCATENATED MODULE: external "@babel/runtime/helpers/objectWithoutProperties"
const objectWithoutProperties_namespaceObject = require("@babel/runtime/helpers/objectWithoutProperties");
var objectWithoutProperties_default = /*#__PURE__*/__webpack_require__.n(objectWithoutProperties_namespaceObject);
;// CONCATENATED MODULE: external "@toruslabs/broadcast-channel"
const broadcast_channel_namespaceObject = require("@toruslabs/broadcast-channel");
;// CONCATENATED MODULE: external "bowser"
const external_bowser_namespaceObject = require("bowser");
var external_bowser_default = /*#__PURE__*/__webpack_require__.n(external_bowser_namespaceObject);
;// CONCATENATED MODULE: external "loglevel"
const external_loglevel_namespaceObject = require("loglevel");
var external_loglevel_default = /*#__PURE__*/__webpack_require__.n(external_loglevel_namespaceObject);
;// CONCATENATED MODULE: ./src/utils/loglevel.ts
/* harmony default export */ const loglevel = (external_loglevel_default().getLogger("customauth"));
;// CONCATENATED MODULE: ./src/utils/helpers.ts
function eventToPromise(emitter) {
return new Promise((resolve, reject) => {
const handler = ev => {
const {
error = "",
data
} = ev;
emitter.removeEventListener("message", handler);
if (error) return reject(new Error(error));
return resolve(data);
};
emitter.addEventListener("message", handler);
});
}
// These are the connection names used by auth0
const loginToConnectionMap = {
[LOGIN.APPLE]: "apple",
[LOGIN.GITHUB]: "github",
[LOGIN.LINKEDIN]: "linkedin",
[LOGIN.TWITTER]: "twitter",
[LOGIN.WEIBO]: "weibo",
[LOGIN.LINE]: "line",
[LOGIN.EMAIL_PASSWORD]: "Username-Password-Authentication",
[LOGIN.PASSWORDLESS]: "email"
};
const padUrlString = url => url.href.endsWith("/") ? url.href : `${url.href}/`;
/**
* Returns a random number. Don't use for cryptographic purposes.
* @returns a random number
*/
const randomId = () => Math.random().toString(36).slice(2);
const broadcastChannelOptions = {
// type: 'localstorage', // (optional) enforce a type, oneOf['native', 'idb', 'localstorage', 'node']
webWorkerSupport: false // (optional) set this to false if you know that your channel will never be used in a WebWorker (increases performance)
};
function caseSensitiveField(field, isCaseSensitive) {
return isCaseSensitive ? field : field.toLowerCase();
}
const getVerifierId = function (userInfo, typeOfLogin, verifierIdField) {
let isVerifierIdCaseSensitive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
const {
name,
sub
} = userInfo;
if (verifierIdField) return caseSensitiveField(userInfo[verifierIdField], isVerifierIdCaseSensitive);
switch (typeOfLogin) {
case LOGIN.PASSWORDLESS:
case LOGIN.EMAIL_PASSWORD:
return caseSensitiveField(name, isVerifierIdCaseSensitive);
case LOGIN.WEIBO:
case LOGIN.GITHUB:
case LOGIN.TWITTER:
case LOGIN.APPLE:
case LOGIN.LINKEDIN:
case LOGIN.LINE:
case LOGIN.JWT:
return caseSensitiveField(sub, isVerifierIdCaseSensitive);
default:
throw new Error("Invalid login type");
}
};
const handleRedirectParameters = (hash, queryParameters) => {
const hashParameters = hash.split("&").reduce((result, item) => {
const [part0, part1] = item.split("=");
result[part0] = part1;
return result;
}, {});
loglevel.info(hashParameters, queryParameters);
let instanceParameters = {};
let error = "";
hashParameters.state = localStorage.getItem("state");
if (Object.keys(hashParameters).length > 0 && hashParameters.state) {
instanceParameters = JSON.parse(atob(decodeURIComponent(decodeURIComponent(hashParameters.state)))) || {};
error = hashParameters.error_description || hashParameters.error || error;
} else if (Object.keys(queryParameters).length > 0 && queryParameters.state) {
instanceParameters = JSON.parse(atob(decodeURIComponent(decodeURIComponent(queryParameters.state)))) || {};
if (queryParameters.error) error = queryParameters.error;
}
localStorage.removeItem("state");
return {
error,
instanceParameters,
hashParameters
};
};
function storageAvailable(type) {
let storage;
try {
storage = window[type];
const x = "__storage_test__";
storage.setItem(x, x);
storage.removeItem(x);
return true;
} catch (e) {
return e && (
// everything except Firefox
e.code === 22 ||
// Firefox
e.code === 1014 ||
// test name field too, because code might not be present
// everything except Firefox
e.name === "QuotaExceededError" ||
// Firefox
e.name === "NS_ERROR_DOM_QUOTA_REACHED") &&
// acknowledge QuotaExceededError only if there's something already stored
storage && storage.length !== 0;
}
}
function getPopupFeatures() {
// Fixes dual-screen position Most browsers Firefox
const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : window.screenX;
const dualScreenTop = window.screenTop !== undefined ? window.screenTop : window.screenY;
const w = 1200;
const h = 700;
const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : window.screen.width;
const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : window.screen.height;
const systemZoom = 1; // No reliable estimate
const left = Math.abs((width - w) / 2 / systemZoom + dualScreenLeft);
const top = Math.abs((height - h) / 2 / systemZoom + dualScreenTop);
const features = `titlebar=0,toolbar=0,status=0,location=0,menubar=0,height=${h / systemZoom},width=${w / systemZoom},top=${top},left=${left}`;
return features;
}
const isFirefox = () => {
var _window;
return ((_window = window) === null || _window === void 0 || (_window = _window.navigator) === null || _window === void 0 ? void 0 : _window.userAgent.toLowerCase().indexOf("firefox")) > -1 || false;
};
function constructURL(params) {
const {
baseURL,
query,
hash
} = params;
const url = new URL(baseURL);
if (query) {
Object.keys(query).forEach(key => {
url.searchParams.append(key, query[key]);
});
}
if (hash) {
const h = new URL(constructURL({
baseURL,
query: hash
})).searchParams.toString();
url.hash = h;
}
return url.toString();
}
function are3PCSupported() {
var _navigator;
const browserInfo = external_bowser_default().parse(navigator.userAgent);
loglevel.info(JSON.stringify(browserInfo), "current browser info");
let thirdPartyCookieSupport = true;
// brave
if ((_navigator = navigator) !== null && _navigator !== void 0 && _navigator.brave) {
thirdPartyCookieSupport = false;
}
// All webkit & gecko engine instances use itp (intelligent tracking prevention -
// https://webkit.org/tracking-prevention/#intelligent-tracking-prevention-itp)
if (browserInfo.engine.name === (external_bowser_default()).ENGINE_MAP.WebKit || browserInfo.engine.name === (external_bowser_default()).ENGINE_MAP.Gecko) {
thirdPartyCookieSupport = false;
}
return thirdPartyCookieSupport;
}
const validateAndConstructUrl = domain => {
try {
const url = new URL(decodeURIComponent(domain));
return url;
} catch (error) {
throw new Error(`${(error === null || error === void 0 ? void 0 : error.message) || ""}, Note: Your jwt domain: (i.e ${domain}) must have http:// or https:// prefix`);
}
};
;// CONCATENATED MODULE: external "events"
const external_events_namespaceObject = require("events");
;// CONCATENATED MODULE: ./src/utils/PopupHandler.ts
class PopupHandler extends external_events_namespaceObject.EventEmitter {
constructor(_ref) {
let {
url,
target,
features
} = _ref;
super();
defineProperty_default()(this, "url", void 0);
defineProperty_default()(this, "target", void 0);
defineProperty_default()(this, "features", void 0);
defineProperty_default()(this, "window", void 0);
defineProperty_default()(this, "windowTimer", void 0);
defineProperty_default()(this, "iClosedWindow", void 0);
this.url = url;
this.target = target || "_blank";
this.features = features || getPopupFeatures();
this.window = undefined;
this.windowTimer = undefined;
this.iClosedWindow = false;
this._setupTimer();
}
_setupTimer() {
this.windowTimer = Number(setInterval(() => {
if (this.window && this.window.closed) {
clearInterval(this.windowTimer);
if (!this.iClosedWindow) {
this.emit("close");
}
this.iClosedWindow = false;
this.window = undefined;
}
if (this.window === undefined) clearInterval(this.windowTimer);
}, 500));
}
open() {
var _this$window;
this.window = window.open(this.url.href, this.target, this.features);
if ((_this$window = this.window) !== null && _this$window !== void 0 && _this$window.focus) this.window.focus();
return Promise.resolve();
}
close() {
this.iClosedWindow = true;
if (this.window) this.window.close();
}
redirect(locationReplaceOnRedirect) {
if (locationReplaceOnRedirect) {
window.location.replace(this.url.href);
} else {
window.location.href = this.url.href;
}
}
}
/* harmony default export */ const utils_PopupHandler = (PopupHandler);
;// CONCATENATED MODULE: ./src/handlers/AbstractLoginHandler.ts
const _excluded = ["access_token", "id_token"];
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { defineProperty_default()(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
class AbstractLoginHandler {
// Not using object constructor because of this issue
// https://github.com/microsoft/TypeScript/issues/5326
constructor(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState) {
this.clientId = clientId;
this.verifier = verifier;
this.redirect_uri = redirect_uri;
this.typeOfLogin = typeOfLogin;
this.uxMode = uxMode;
this.redirectToOpener = redirectToOpener;
this.jwtParams = jwtParams;
this.customState = customState;
defineProperty_default()(this, "nonce", randomId());
defineProperty_default()(this, "finalURL", void 0);
}
get state() {
return encodeURIComponent(window.btoa(JSON.stringify(_objectSpread(_objectSpread({}, this.customState || {}), {}, {
instanceId: this.nonce,
verifier: this.verifier,
typeOfLogin: this.typeOfLogin,
redirectToOpener: this.redirectToOpener || false
}))));
}
handleLoginWindow(params) {
const verifierWindow = new utils_PopupHandler({
url: this.finalURL,
features: params.popupFeatures
});
if (this.uxMode === UX_MODE.REDIRECT) {
verifierWindow.redirect(params.locationReplaceOnRedirect);
} else {
return new Promise((resolve, reject) => {
let bc;
const handleData = async ev => {
try {
const {
error,
data
} = ev;
const _ref = data || {},
{
instanceParams,
hashParams: {
access_token: accessToken,
id_token: idToken
}
} = _ref,
rest = objectWithoutProperties_default()(_ref.hashParams, _excluded);
if (error) {
loglevel.error(ev);
reject(new Error(`Error: ${error}. Info: ${JSON.stringify(ev.data || {})}`));
return;
}
if (ev.data && instanceParams.verifier === this.verifier) {
loglevel.info(ev.data);
if (!this.redirectToOpener && bc) await bc.postMessage({
success: true
});
resolve(_objectSpread(_objectSpread({
accessToken,
idToken: idToken || ""
}, rest), {}, {
// State has to be last here otherwise it will be overwritten
state: instanceParams
}));
}
} catch (error) {
loglevel.error(error);
reject(error);
}
};
if (!this.redirectToOpener) {
bc = new broadcast_channel_namespaceObject.BroadcastChannel(`redirect_channel_${this.nonce}`, broadcastChannelOptions);
bc.addEventListener("message", async ev => {
await handleData(ev);
bc.close();
verifierWindow.close();
});
} else {
const postMessageEventHandler = async postMessageEvent => {
if (!postMessageEvent.data) return;
const ev = postMessageEvent.data;
if (ev.channel !== `redirect_channel_${this.nonce}`) return;
window.removeEventListener("message", postMessageEventHandler);
handleData(ev);
verifierWindow.close();
};
window.addEventListener("message", postMessageEventHandler);
}
verifierWindow.open();
verifierWindow.once("close", () => {
if (bc) bc.close();
reject(new Error("user closed popup"));
});
});
}
return null;
}
}
/* harmony default export */ const handlers_AbstractLoginHandler = (AbstractLoginHandler);
;// CONCATENATED MODULE: ./src/handlers/DiscordHandler.ts
class DiscordHandler extends handlers_AbstractLoginHandler {
constructor(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState) {
super(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState);
this.clientId = clientId;
this.verifier = verifier;
this.redirect_uri = redirect_uri;
this.typeOfLogin = typeOfLogin;
this.uxMode = uxMode;
this.redirectToOpener = redirectToOpener;
this.jwtParams = jwtParams;
this.customState = customState;
defineProperty_default()(this, "RESPONSE_TYPE", "token");
defineProperty_default()(this, "SCOPE", "identify email");
this.setFinalUrl();
}
setFinalUrl() {
const finalUrl = new URL("https://discord.com/api/oauth2/authorize");
const clonedParams = JSON.parse(JSON.stringify(this.jwtParams || {}));
const finalJwtParams = external_lodash_merge_default()({
state: this.state,
response_type: this.RESPONSE_TYPE,
client_id: this.clientId,
redirect_uri: this.redirect_uri,
scope: this.SCOPE
}, clonedParams);
Object.keys(finalJwtParams).forEach(key => {
if (finalJwtParams[key]) finalUrl.searchParams.append(key, finalJwtParams[key]);
});
this.finalURL = finalUrl;
}
async getUserInfo(params) {
const {
accessToken
} = params;
const userInfo = await (0,http_helpers_namespaceObject.get)("https://discord.com/api/users/@me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const {
id,
avatar,
email = "",
username: name = "",
discriminator = ""
} = userInfo;
const profileImage = avatar === null ? `https://cdn.discordapp.com/embed/avatars/${Number(discriminator) % 5}.png` : `https://cdn.discordapp.com/avatars/${id}/${avatar}.png?size=2048`;
return {
profileImage,
name: `${name}#${discriminator}`,
email,
verifierId: id,
verifier: this.verifier,
typeOfLogin: this.typeOfLogin
};
}
}
;// CONCATENATED MODULE: ./src/handlers/FacebookHandler.ts
class FacebookHandler extends handlers_AbstractLoginHandler {
constructor(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState) {
super(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState);
this.clientId = clientId;
this.verifier = verifier;
this.redirect_uri = redirect_uri;
this.typeOfLogin = typeOfLogin;
this.uxMode = uxMode;
this.redirectToOpener = redirectToOpener;
this.jwtParams = jwtParams;
this.customState = customState;
defineProperty_default()(this, "RESPONSE_TYPE", "token");
defineProperty_default()(this, "SCOPE", "public_profile email");
this.setFinalUrl();
}
setFinalUrl() {
const finalUrl = new URL("https://www.facebook.com/v15.0/dialog/oauth");
const clonedParams = JSON.parse(JSON.stringify(this.jwtParams || {}));
const finalJwtParams = external_lodash_merge_default()({
state: this.state,
response_type: this.RESPONSE_TYPE,
client_id: this.clientId,
redirect_uri: this.redirect_uri,
scope: this.SCOPE
}, clonedParams);
Object.keys(finalJwtParams).forEach(key => {
if (finalJwtParams[key]) finalUrl.searchParams.append(key, finalJwtParams[key]);
});
this.finalURL = finalUrl;
}
async getUserInfo(params) {
const {
accessToken
} = params;
const userInfo = await (0,http_helpers_namespaceObject.get)("https://graph.facebook.com/me?fields=name,email,picture.type(large)", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const {
name = "",
id,
picture,
email = ""
} = userInfo;
return {
email,
name,
profileImage: picture.data.url || "",
verifier: this.verifier,
verifierId: id,
typeOfLogin: this.typeOfLogin
};
}
}
;// CONCATENATED MODULE: ./src/handlers/GoogleHandler.ts
class GoogleHandler extends handlers_AbstractLoginHandler {
constructor(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState) {
super(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState);
this.clientId = clientId;
this.verifier = verifier;
this.redirect_uri = redirect_uri;
this.typeOfLogin = typeOfLogin;
this.uxMode = uxMode;
this.redirectToOpener = redirectToOpener;
this.jwtParams = jwtParams;
this.customState = customState;
defineProperty_default()(this, "RESPONSE_TYPE", "token id_token");
defineProperty_default()(this, "SCOPE", "profile email openid");
defineProperty_default()(this, "PROMPT", "consent select_account");
this.setFinalUrl();
}
setFinalUrl() {
const finalUrl = new URL("https://accounts.google.com/o/oauth2/v2/auth");
const clonedParams = JSON.parse(JSON.stringify(this.jwtParams || {}));
const finalJwtParams = external_lodash_merge_default()({
state: this.state,
response_type: this.RESPONSE_TYPE,
client_id: this.clientId,
prompt: this.PROMPT,
redirect_uri: this.redirect_uri,
scope: this.SCOPE,
nonce: this.nonce
}, clonedParams);
Object.keys(finalJwtParams).forEach(key => {
if (finalJwtParams[key]) finalUrl.searchParams.append(key, finalJwtParams[key]);
});
this.finalURL = finalUrl;
}
async getUserInfo(params) {
const {
accessToken
} = params;
const userInfo = await (0,http_helpers_namespaceObject.get)("https://www.googleapis.com/userinfo/v2/me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const {
picture: profileImage = "",
email = "",
name = ""
} = userInfo;
return {
email,
name,
profileImage,
verifier: this.verifier,
verifierId: email.toLowerCase(),
typeOfLogin: this.typeOfLogin
};
}
}
;// CONCATENATED MODULE: external "jwt-decode"
const external_jwt_decode_namespaceObject = require("jwt-decode");
var external_jwt_decode_default = /*#__PURE__*/__webpack_require__.n(external_jwt_decode_namespaceObject);
;// CONCATENATED MODULE: ./src/handlers/JwtHandler.ts
class JwtHandler extends handlers_AbstractLoginHandler {
constructor(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState) {
super(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState);
this.clientId = clientId;
this.verifier = verifier;
this.redirect_uri = redirect_uri;
this.typeOfLogin = typeOfLogin;
this.uxMode = uxMode;
this.redirectToOpener = redirectToOpener;
this.jwtParams = jwtParams;
this.customState = customState;
defineProperty_default()(this, "SCOPE", "openid profile email");
defineProperty_default()(this, "RESPONSE_TYPE", "token id_token");
defineProperty_default()(this, "PROMPT", "login");
this.setFinalUrl();
}
setFinalUrl() {
localStorage.setItem("state", this.state);
const {
domain
} = this.jwtParams;
const finalUrl = validateAndConstructUrl(domain);
finalUrl.pathname += finalUrl.pathname.endsWith("/") ? "authorize" : "/authorize";
const clonedParams = JSON.parse(JSON.stringify(this.jwtParams));
delete clonedParams.domain;
const finalJwtParams = external_lodash_merge_default()({
state: this.state,
response_type: this.RESPONSE_TYPE,
client_id: this.clientId,
prompt: this.PROMPT,
redirect_uri: this.redirect_uri,
scope: this.SCOPE,
connection: loginToConnectionMap[this.typeOfLogin],
nonce: this.nonce
}, clonedParams);
Object.keys(finalJwtParams).forEach(key => {
if (finalJwtParams[key]) finalUrl.searchParams.append(key, finalJwtParams[key]);
});
this.finalURL = finalUrl;
}
async getUserInfo(params) {
const {
idToken,
accessToken
} = params;
const {
domain,
verifierIdField,
isVerifierIdCaseSensitive,
user_info_route = "userinfo"
} = this.jwtParams;
if (accessToken) {
try {
const domainUrl = new URL(domain);
const userInfo = await (0,http_helpers_namespaceObject.get)(`${padUrlString(domainUrl)}${user_info_route}`, {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const {
picture,
name,
email
} = userInfo;
return {
email,
name,
profileImage: picture,
verifierId: getVerifierId(userInfo, this.typeOfLogin, verifierIdField, isVerifierIdCaseSensitive),
verifier: this.verifier,
typeOfLogin: this.typeOfLogin
};
} catch (error) {
// ignore
external_loglevel_default().warn(error, "Unable to get userinfo from endpoint");
}
}
if (idToken) {
const decodedToken = external_jwt_decode_default()(idToken);
const {
name,
email,
picture
} = decodedToken;
return {
profileImage: picture,
name,
email,
verifierId: getVerifierId(decodedToken, this.typeOfLogin, verifierIdField, isVerifierIdCaseSensitive),
verifier: this.verifier,
typeOfLogin: this.typeOfLogin
};
}
throw new Error("Access/id token not available");
}
}
;// CONCATENATED MODULE: ./src/handlers/MockLoginHandler.ts
class MockLoginHandler extends handlers_AbstractLoginHandler {
constructor(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState) {
super(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState);
this.clientId = clientId;
this.verifier = verifier;
this.redirect_uri = redirect_uri;
this.typeOfLogin = typeOfLogin;
this.uxMode = uxMode;
this.redirectToOpener = redirectToOpener;
this.jwtParams = jwtParams;
this.customState = customState;
this.setFinalUrl();
}
setFinalUrl() {
const clonedParams = JSON.parse(JSON.stringify(this.jwtParams));
delete clonedParams.domain;
const finalJwtParams = external_lodash_merge_default()({
state: this.state,
client_id: this.clientId,
nonce: this.nonce
}, clonedParams);
this.finalURL = new URL(constructURL({
baseURL: this.redirect_uri,
query: null,
hash: finalJwtParams
}));
}
async getUserInfo(params) {
const {
idToken,
accessToken
} = params;
const {
domain,
verifierIdField,
isVerifierIdCaseSensitive,
user_info_route = "userinfo"
} = this.jwtParams;
if (accessToken) {
try {
const domainUrl = new URL(domain);
const userInfo = await (0,http_helpers_namespaceObject.get)(`${padUrlString(domainUrl)}${user_info_route}`, {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const {
picture,
name,
email
} = userInfo;
return {
email,
name,
profileImage: picture,
verifierId: getVerifierId(userInfo, this.typeOfLogin, verifierIdField, isVerifierIdCaseSensitive),
verifier: this.verifier,
typeOfLogin: this.typeOfLogin
};
} catch (error) {
// ignore
external_loglevel_default().warn(error, "Unable to get userinfo from endpoint");
}
}
if (idToken) {
const decodedToken = external_jwt_decode_default()(idToken);
const {
name,
email,
picture
} = decodedToken;
return {
profileImage: picture,
name,
email,
verifierId: getVerifierId(decodedToken, this.typeOfLogin, verifierIdField, isVerifierIdCaseSensitive),
verifier: this.verifier,
typeOfLogin: this.typeOfLogin
};
}
throw new Error("Access/id token not available");
}
handleLoginWindow(params) {
const {
id_token: idToken,
access_token: accessToken
} = this.jwtParams;
const verifierWindow = new utils_PopupHandler({
url: this.finalURL,
features: params.popupFeatures
});
if (this.uxMode === UX_MODE.REDIRECT) {
verifierWindow.redirect(params.locationReplaceOnRedirect);
} else {
return Promise.resolve({
state: {},
idToken,
accessToken
});
}
return null;
}
}
;// CONCATENATED MODULE: ./src/handlers/PasswordlessHandler.ts
const PasswordlessHandler_excluded = ["access_token", "id_token"];
function PasswordlessHandler_ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function PasswordlessHandler_objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? PasswordlessHandler_ownKeys(Object(t), !0).forEach(function (r) { defineProperty_default()(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : PasswordlessHandler_ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
class PasswordlessHandler_JwtHandler extends handlers_AbstractLoginHandler {
constructor(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState) {
super(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState);
this.clientId = clientId;
this.verifier = verifier;
this.redirect_uri = redirect_uri;
this.typeOfLogin = typeOfLogin;
this.uxMode = uxMode;
this.redirectToOpener = redirectToOpener;
this.jwtParams = jwtParams;
this.customState = customState;
defineProperty_default()(this, "SCOPE", "openid profile email");
defineProperty_default()(this, "RESPONSE_TYPE", "token id_token");
defineProperty_default()(this, "PROMPT", "login");
this.setFinalUrl();
}
setFinalUrl() {
const {
domain
} = this.jwtParams;
const domainUrl = validateAndConstructUrl(domain);
domainUrl.pathname = "/passwordless/start";
this.finalURL = domainUrl;
}
async getUserInfo(params) {
const {
idToken,
accessToken
} = params;
const {
domain,
verifierIdField,
isVerifierIdCaseSensitive
} = this.jwtParams;
try {
const domainUrl = new URL(domain);
const userInfo = await (0,http_helpers_namespaceObject.get)(`${padUrlString(domainUrl)}userinfo`, {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const {
picture,
name,
email
} = userInfo;
return {
email,
name,
profileImage: picture,
verifierId: getVerifierId(userInfo, this.typeOfLogin, verifierIdField, isVerifierIdCaseSensitive),
verifier: this.verifier,
typeOfLogin: this.typeOfLogin
};
} catch (error) {
loglevel.error(error);
const decodedToken = external_jwt_decode_default()(idToken);
const {
name,
email,
picture
} = decodedToken;
return {
profileImage: picture,
name,
email,
verifierId: getVerifierId(decodedToken, this.typeOfLogin, verifierIdField, isVerifierIdCaseSensitive),
verifier: this.verifier,
typeOfLogin: this.typeOfLogin
};
}
}
handleLoginWindow() {
return new Promise((resolve, reject) => {
if (this.redirectToOpener) {
reject(new Error("Cannot use redirect to opener for passwordless"));
return;
}
const handleData = ev => {
try {
const {
error,
data
} = ev;
const _ref = data || {},
{
instanceParams,
hashParams: {
access_token: accessToken,
id_token: idToken
}
} = _ref,
rest = objectWithoutProperties_default()(_ref.hashParams, PasswordlessHandler_excluded);
if (error) {
loglevel.error(ev.error);
reject(new Error(error));
return;
}
if (ev.data && instanceParams.verifier === this.verifier) {
loglevel.info(ev.data);
resolve(PasswordlessHandler_objectSpread(PasswordlessHandler_objectSpread({
accessToken,
idToken: idToken || ""
}, rest), {}, {
state: instanceParams
}));
}
} catch (error) {
loglevel.error(error);
reject(error);
}
};
const bc = new broadcast_channel_namespaceObject.BroadcastChannel(`redirect_channel_${this.nonce}`, broadcastChannelOptions);
bc.addEventListener("message", async ev => {
handleData(ev);
bc.close();
});
try {
const {
connection = "email",
login_hint
} = this.jwtParams;
const finalJwtParams = external_lodash_merge_default()({
client_id: this.clientId,
connection,
email: connection === "email" ? login_hint : undefined,
phone_number: connection === "sms" ? login_hint : undefined,
send: "link",
authParams: {
scope: this.SCOPE,
state: this.state,
response_type: this.RESPONSE_TYPE,
redirect_uri: this.redirect_uri,
nonce: this.nonce,
prompt: this.PROMPT
}
}, {
authParams: this.jwtParams
});
// using stringify and parse to remove undefined params
// This method is only resolved when the user clicks the email link
(0,http_helpers_namespaceObject.post)(this.finalURL.href, JSON.parse(JSON.stringify(finalJwtParams))).then(response => {
loglevel.info("posted", response);
return undefined;
}).catch(error => {
loglevel.error(error);
reject(error);
});
} catch (error) {
loglevel.error(error);
reject(error);
}
});
}
}
;// CONCATENATED MODULE: ./src/handlers/RedditHandler.ts
class RedditHandler extends handlers_AbstractLoginHandler {
constructor(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState) {
super(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState);
this.clientId = clientId;
this.verifier = verifier;
this.redirect_uri = redirect_uri;
this.typeOfLogin = typeOfLogin;
this.uxMode = uxMode;
this.redirectToOpener = redirectToOpener;
this.jwtParams = jwtParams;
this.customState = customState;
defineProperty_default()(this, "RESPONSE_TYPE", "token");
defineProperty_default()(this, "SCOPE", "identity");
this.setFinalUrl();
}
setFinalUrl() {
const finalUrl = new URL(`https://www.reddit.com/api/v1/authorize${window.innerWidth < 600 ? ".compact" : ""}`);
const clonedParams = JSON.parse(JSON.stringify(this.jwtParams || {}));
const finalJwtParams = external_lodash_merge_default()({
state: this.state,
response_type: this.RESPONSE_TYPE,
client_id: this.clientId,
redirect_uri: this.redirect_uri,
scope: this.SCOPE
}, clonedParams);
Object.keys(finalJwtParams).forEach(key => {
if (finalJwtParams[key]) finalUrl.searchParams.append(key, finalJwtParams[key]);
});
this.finalURL = finalUrl;
}
async getUserInfo(params) {
const {
accessToken
} = params;
const userInfo = await (0,http_helpers_namespaceObject.get)("https://oauth.reddit.com/api/v1/me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const {
icon_img: profileImage = "",
name = ""
} = userInfo;
return {
email: "",
name,
profileImage: profileImage.split("?").length > 0 ? profileImage.split("?")[0] : profileImage,
verifier: this.verifier,
verifierId: name.toLowerCase(),
typeOfLogin: this.typeOfLogin
};
}
}
;// CONCATENATED MODULE: ./src/handlers/TwitchHandler.ts
class TwitchHandler extends handlers_AbstractLoginHandler {
constructor(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState) {
super(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState);
this.clientId = clientId;
this.verifier = verifier;
this.redirect_uri = redirect_uri;
this.typeOfLogin = typeOfLogin;
this.uxMode = uxMode;
this.redirectToOpener = redirectToOpener;
this.jwtParams = jwtParams;
this.customState = customState;
defineProperty_default()(this, "RESPONSE_TYPE", "token");
defineProperty_default()(this, "SCOPE", "user:read:email");
this.setFinalUrl();
}
setFinalUrl() {
const finalUrl = new URL("https://id.twitch.tv/oauth2/authorize");
const clonedParams = JSON.parse(JSON.stringify(this.jwtParams || {}));
const finalJwtParams = external_lodash_merge_default()({
state: this.state,
response_type: this.RESPONSE_TYPE,
client_id: this.clientId,
redirect_uri: this.redirect_uri,
scope: this.SCOPE,
force_verify: true
}, clonedParams);
Object.keys(finalJwtParams).forEach(key => {
if (finalJwtParams[key]) finalUrl.searchParams.append(key, finalJwtParams[key]);
});
this.finalURL = finalUrl;
}
async getUserInfo(params) {
const {
accessToken
} = params;
const userInfo = await (0,http_helpers_namespaceObject.get)("https://api.twitch.tv/helix/users", {
headers: {
Authorization: `Bearer ${accessToken}`,
"Client-ID": this.clientId
}
});
const [{
profile_image_url: profileImage = "",
display_name: name = "",
email = "",
id: verifierId
}] = userInfo.data || [];
return {
profileImage,
name,
email,
verifierId,
verifier: this.verifier,
typeOfLogin: this.typeOfLogin
};
}
}
;// CONCATENATED MODULE: ./src/handlers/WebAuthnHandler.ts
const WEBAUTHN_LOOKUP_SERVER = "https://api.webauthn.openlogin.com";
class WebAuthnHandler extends handlers_AbstractLoginHandler {
constructor(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState, registerOnly) {
super(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState);
this.clientId = clientId;
this.verifier = verifier;
this.redirect_uri = redirect_uri;
this.typeOfLogin = typeOfLogin;
this.uxMode = uxMode;
this.redirectToOpener = redirectToOpener;
this.jwtParams = jwtParams;
this.customState = customState;
this.registerOnly = registerOnly;
this.setFinalUrl();
}
setFinalUrl() {
const finalUrl = new URL("https://webauthn.openlogin.com");
const clonedParams = JSON.parse(JSON.stringify(this.jwtParams || {}));
const finalJwtParams = external_lodash_merge_default()({
register_only: !!this.registerOnly,
state: this.state,
client_id: this.clientId,
redirect_uri: this.redirect_uri
}, clonedParams);
Object.keys(finalJwtParams).forEach(key => {
if (finalJwtParams[key]) finalUrl.searchParams.append(key, finalJwtParams[key]);
});
this.finalURL = finalUrl;
}
async getUserInfo(parameters) {
const {
idToken,
ref,
extraParamsPassed,
extraParams
} = parameters;
let verifierId;
let signature;
let clientDataJSON;
let authenticatorData;
let publicKey;
let challenge;
let rpOrigin;
let credId;
let transports;
if (extraParamsPassed === "true") {
loglevel.debug("extraParamsPassed is true, using extraParams passed through hashParams");
try {
({
verifier_id: verifierId,
signature,
clientDataJSON,
authenticatorData,
publicKey,
challenge,
rpOrigin,
credId,
transports
} = JSON.parse(atob(extraParams)));
} catch (error) {
loglevel.warn("unable to parse extraParams", error);
({
verifier_id: verifierId,
signature,
clientDataJSON,
authenticatorData,
publicKey,
challenge,
rpOrigin,
credId,
transports
} = await (0,http_helpers_namespaceObject.get)(`${WEBAUTHN_LOOKUP_SERVER}/signature/fetch/${idToken}`));
}
} else {
loglevel.debug("extraParamsPassed is false, using extraParams passed through bridge server");
({
verifier_id: verifierId,
signature,
clientDataJSON,
authenticatorData,
publicKey,
challenge,
rpOrigin,
credId,
transports
} = await (0,http_helpers_namespaceObject.get)(`${WEBAUTHN_LOOKUP_SERVER}/signature/fetch/${idToken}`));
}
if (signature !== idToken) {
throw new Error("idtoken should be equal to signature");
}
return {
email: "",
name: "WebAuthn Login",
profileImage: "",
verifier: this.verifier,
verifierId,
typeOfLogin: this.typeOfLogin,
ref,
registerOnly: this.registerOnly,
extraVerifierParams: {
signature,
clientDataJSON,
authenticatorData,
publicKey,
challenge,
rpOrigin,
credId,
transports
}
};
}
}
;// CONCATENATED MODULE: ./src/handlers/HandlerFactory.ts
const createHandler = _ref => {
let {
clientId,
redirect_uri,
typeOfLogin,
verifier,
jwtParams,
redirectToOpener,
uxMode,
customState,
registerOnly
} = _ref;
if (!verifier || !typeOfLogin || !clientId) {
throw new Error("Invalid params");
}
const {
domain,
login_hint,
id_token,
access_token
} = jwtParams || {};
switch (typeOfLogin) {
case LOGIN.GOOGLE:
return new GoogleHandler(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState);
case LOGIN.FACEBOOK:
return new FacebookHandler(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState);
case LOGIN.TWITCH:
return new TwitchHandler(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState);
case LOGIN.REDDIT:
return new RedditHandler(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState);
case LOGIN.DISCORD:
return new DiscordHandler(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState);
case LOGIN.PASSWORDLESS:
if (!domain || !login_hint) throw new Error("Invalid params");
return new PasswordlessHandler_JwtHandler(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState);
case LOGIN.APPLE:
case LOGIN.GITHUB:
case LOGIN.LINKEDIN:
case LOGIN.TWITTER:
case LOGIN.WEIBO:
case LOGIN.LINE:
case LOGIN.EMAIL_PASSWORD:
case LOGIN.JWT:
if (id_token || access_token) {
return new MockLoginHandler(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState);
}
if (!domain) throw new Error("Invalid params");
return new JwtHandler(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState);
case LOGIN.WEBAUTHN:
return new WebAuthnHandler(clientId, verifier, redirect_uri, typeOfLogin, uxMode, redirectToOpener, jwtParams, customState, registerOnly);
default:
throw new Error("Invalid login type");
}
};
/* harmony default export */ const HandlerFactory = (createHandler);
;// CONCATENATED MODULE: external "@toruslabs/constants"
const constants_namespaceObject = require("@toruslabs/constants");
;// CONCATENATED MODULE: external "@toruslabs/fetch-node-details"
const fetch_node_details_namespaceObject = require("@toruslabs/fetch-node-details");
;// CONCATENATED MODULE: external "@toruslabs/torus.js"
const torus_js_namespaceObject = require("@toruslabs/torus.js");
var torus_js_default = /*#__PURE__*/__webpack_require__.n(torus_js_namespaceObject);
;// CONCATENATED MODULE: external "oidc-client"
const external_oidc_client_namespaceObject = require("oidc-client");
;// CONCATENATED MODULE: external "@chaitanyapotti/register-service-worker"
const register_service_worker_namespaceObject = require("@chaitanyapotti/register-service-worker");
;// CONCATENATED MODULE: ./src/registerServiceWorker.ts
const registerServiceWorker = baseUrl => new Promise((resolve, reject) => {
const swUrl = `${baseUrl}sw.js`;
if ("serviceWorker" in window.navigator) {
// if swIntegrity is not calculated
(0,register_service_worker_namespaceObject.register)(swUrl, {
ready() {
loglevel.info("App is being served from cache by a service worker.\n For more details, visit https://goo.gl/AFskqB");
resolve(undefined);
},
registered() {
loglevel.info("Service worker has been registered.");
resolve(undefined);
},
cached() {
loglevel.info("Content has been cached for offline use.");
resolve(undefined);
},
updatefound() {
loglevel.info("New content is downloading.");
},
updated() {
loglevel.info("New content is available; please refresh.");
},
offline() {
loglevel.info("No internet connection found. App is running in offline mode.");
reject(new Error("App is offline"));
},
error(error) {
loglevel.error("Error during service worker registration:", error);
reject(error);
}
});
} else {
reject(new Error("Service workers are not supported"));
}
});
;// CONCATENATED MODULE: ./src/sentry.ts
class SentryHandler {
constructor(sentry) {
defineProperty_default()(this, "sentry", null);
this.sentry = sentry;
}
startTransaction(context) {
if (this.sentry) {
return this.sentry.startTransaction(context);
}
}
finishTransaction(tx) {
if (tx) {
tx.finish();
}
}
}
;// CONCATENATED MODULE: external "@toruslabs/eccrypto"
const eccrypto_namespaceObject = require("@toruslabs/eccrypto");
;// CONCATENATED MODULE: external "@toruslabs/metadata-helpers"
const metadata_he