UNPKG

@venly/connect

Version:

Venly Connect SDK

466 lines • 23.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Security = void 0; var tslib_1 = require("tslib"); var WindowMode_1 = require("../models/WindowMode"); var PopupWindowAsync_1 = require("../popup/PopupWindowAsync"); var EventTypes_1 = require("../types/EventTypes"); var Utils_1 = tslib_1.__importDefault(require("../utils/Utils")); var DialogWindow_1 = require("../dialog/DialogWindow"); var Security = /** @class */ (function () { function Security() { } Security.getConfig = function (clientId) { return { 'clientId': clientId, 'realm': 'Arkane', 'url': Utils_1.default.urls.login, 'ssl-required': 'external', 'public-client': 'true', }; }; Security.login = function (clientId, options, cid) { if (options && options.idpHint && (options.idpHint === 'twitter' || options.idpHint === 'facebook')) { options.idpHint = 'arkane-' + options.idpHint; } switch (options && options.windowMode) { case WindowMode_1.WindowMode.POPUP: return Security.loginPopup(clientId, !!cid ? cid : Utils_1.default.uuidv4(), options); case WindowMode_1.WindowMode.DIALOG: return DialogWindow_1.DialogWindow.openLoginDialog(clientId, options); default: return Security.loginRedirect(clientId, options); } }; Security.loginRedirect = function (clientId, options) { var config = Security.getConfig(clientId); var loginOptions = {}; if (options) { if (options.idpHint) { loginOptions.idpHint = options.idpHint; if (options.idpHint === 'password' && options.emailHint) { loginOptions.loginHint = options.emailHint; } } if (options.redirectUri) { loginOptions.redirectUri = options.redirectUri; } } return this.keycloakLogin(config, loginOptions); }; Security.loginPopup = function (clientId, cid, options) { var closePopup = options ? options.closePopup : true; return Promise.race([ Security.initialiseAuthenticatedListener(clientId, EventTypes_1.EventTypes.AUTHENTICATE, cid, closePopup), Security.initialiseLoginPopup(clientId, cid, options), ]); }; Security.checkAuthenticated = function (clientId, options) { if ((options && options.windowMode) === WindowMode_1.WindowMode.REDIRECT) { var initOptions = { onLoad: 'check-sso', checkLoginIframe: false, }; if (options.redirectUri) { initOptions.redirectUri = options.redirectUri; } return Security.initKeycloak(Security.getConfig(clientId), initOptions); } else { var authenticatedPromise = Security.initialiseAuthenticatedListener(clientId, EventTypes_1.EventTypes.CHECK_AUTHENTICATED, Utils_1.default.uuidv4()); Security.initialiseCheckAuthenticatedIFrame(clientId); return authenticatedPromise; } }; Security.logout = function (auth) { var _this = this; if (auth.authenticated && auth.clientId) { return new Promise(function (resolve, reject) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var params_1, searchParams, _a; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: if (!auth.clientId) return [3 /*break*/, 3]; params_1 = { client_id: auth.clientId, id_token_hint: auth.idToken, refresh_token: auth.refreshToken }; searchParams = Object.keys(params_1).map(function (key) { return encodeURIComponent(key) + '=' + encodeURIComponent(params_1[key]); }).join('&'); return [4 /*yield*/, fetch(Utils_1.default.urls.login + '/realms/Arkane/protocol/openid-connect/logout', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' }, body: searchParams })]; case 1: _b.sent(); _a = Security; return [4 /*yield*/, Security.createLogoutListener(EventTypes_1.EventTypes.LOGOUT, auth, resolve, reject)]; case 2: _a.logoutListener = _b.sent(); window.addEventListener('message', Security.logoutListener); Security.initialiseLogoutIFrame(auth.clientId); _b.label = 3; case 3: return [2 /*return*/]; } }); }); }); } else { return Promise.resolve(); } }; Security.hasPopupWindow = function () { return !!this.popupWindow; }; Security.closePopupWindow = function () { if (Security.popupWindow && !Security.popupWindow.closed) { Security.popupWindow.close(); delete Security.popupWindow; } }; Security.focusPopupWindow = function () { if (Security.popupWindow && !Security.popupWindow.closed) { Security.popupWindow.focus(); } }; Object.defineProperty(Security, "checkAuthenticatedURI", { get: function () { return Utils_1.default.urls.connect + "/checkAuthenticated"; }, enumerable: false, configurable: true }); Object.defineProperty(Security, "authenticateURI", { get: function () { return Utils_1.default.urls.connect + "/authenticate"; }, enumerable: false, configurable: true }); Object.defineProperty(Security, "logoutURI", { get: function () { return Utils_1.default.urls.connect + "/logout"; }, enumerable: false, configurable: true }); Security.initialiseLoginPopup = function (clientId, cid, options) { return tslib_1.__awaiter(this, void 0, void 0, function () { var origin, url, kcIdpHint, loginHint, _a; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: origin = window.location.href.replace(window.location.search, ''); url = Security.authenticateURI + "?" + new URLSearchParams({ clientId: clientId, origin: origin, env: Utils_1.default.rawEnvironment }).toString(); if (options && options.idpHint) { kcIdpHint = options.idpHint; url += "&" + new URLSearchParams({ kc_idp_hint: kcIdpHint }).toString(); } if (options && options.emailHint && options.idpHint === 'password') { loginHint = options.emailHint; url += "&" + new URLSearchParams({ login_hint: loginHint }).toString(); } _a = this; return [4 /*yield*/, PopupWindowAsync_1.PopupWindowAsync.openNew(url, cid, { useOverlay: false })]; case 1: _a.popupWindow = _b.sent(); return [2 /*return*/, Security.initialiseIsLoginPopupClosedInterval(cid)]; } }); }); }; Security.initialiseIsLoginPopupClosedInterval = function (cid) { return new Promise(function (resolve, reject) { Security.isLoginPopupClosedInterval = window.setInterval(function () { var popupWindow = Security.popupWindow; if (popupWindow && popupWindow.closed) { Security.clearIsLoginPopupClosedInterval(); Security.cleanUp(EventTypes_1.EventTypes.AUTHENTICATE, cid); resolve({ authenticated: false }); } }, 2000); }); }; Security.clearIsLoginPopupClosedInterval = function () { clearInterval(Security.isLoginPopupClosedInterval); delete Security.isLoginPopupClosedInterval; }; Security.initialiseCheckAuthenticatedIFrame = function (clientId) { return this.initialiseIFrame(clientId, Security.AUTH_IFRAME_ID, Security.checkAuthenticatedURI); }; Security.initialiseLogoutIFrame = function (clientId) { return this.initialiseIFrame(clientId, Security.LOGOUT_IFRAME_ID, Security.logoutURI); }; Security.initialiseIFrame = function (clientId, iframeID, uri) { var iframe = document.getElementById(iframeID); var isIframeInBody = true; if (!iframe) { isIframeInBody = false; iframe = document.createElement('iframe'); } var origin = window.location.href.replace(window.location.search, ''); iframe.src = uri + "?" + new URLSearchParams({ clientId: clientId, origin: origin, env: Utils_1.default.rawEnvironment }).toString(); iframe.hidden = true; iframe.id = iframeID; iframe.setAttribute('style', 'display: none!important;'); document.body.appendChild(iframe); if (!isIframeInBody) { document.body.appendChild(iframe); } return iframe; }; Security.setUpdateTokenInterval = function () { var _this = this; if (Security.updateTokenInterval) { clearInterval(Security.updateTokenInterval); Security.updateTokenInterval = null; } Security.updateTokenInterval = setInterval(function () { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { new Promise(function (resolve, reject) { if (Security.keycloak) { Security.keycloak.updateToken(70).then(function (refreshed) { resolve(refreshed); }); } else { reject(false); } }).then(function (refreshed) { if (refreshed) { if (Security.onTokenUpdate && Security.keycloak.token) { Security.onTokenUpdate(Security.keycloak.token); } } }).catch(function () { console.error('failed to refresh token'); clearInterval(Security.updateTokenInterval); Security.updateTokenInterval = null; }); return [2 /*return*/]; }); }); }, 60000); }; Security.forceUpdateToken = function () { var _a; return tslib_1.__awaiter(this, void 0, void 0, function () { var refreshed; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: return [4 /*yield*/, ((_a = Security.keycloak) === null || _a === void 0 ? void 0 : _a.updateToken(300))]; case 1: refreshed = _b.sent(); if (refreshed) { if (Security.onTokenUpdate && Security.keycloak.token) { Security.onTokenUpdate(Security.keycloak.token); } } return [2 /*return*/]; } }); }); }; Security.keycloakLogin = function (config, loginOptions) { return tslib_1.__awaiter(this, void 0, void 0, function () { var Keycloak; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, Promise.resolve().then(function () { return tslib_1.__importStar(require('keycloak-js')); })]; case 1: Keycloak = _a.sent(); Security.keycloak = Keycloak.default(config); return [2 /*return*/, new Promise(function (resolve, reject) { Security.keycloak .init({}) .then(function () { return Security.keycloak .login(loginOptions) .then(function (authenticated) { if (authenticated) { Security.setUpdateTokenInterval(); } resolve({ keycloak: Security.keycloak, authenticated: authenticated, }); }) .catch(function (e) { reject(e); }); }); })]; } }); }); }; Security.initKeycloak = function (config, initOptions) { return tslib_1.__awaiter(this, void 0, void 0, function () { var Keycloak; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, Promise.resolve().then(function () { return tslib_1.__importStar(require('keycloak-js')); })]; case 1: Keycloak = _a.sent(); Security.keycloak = Keycloak.default(config); return [2 /*return*/, new Promise(function (resolve, reject) { Security.keycloak .init(initOptions) .then(function (authenticated) { if (authenticated) { Security.setUpdateTokenInterval(); } Security.removeLoginState(); resolve({ keycloak: Security.keycloak, authenticated: authenticated, }); }) .catch(function (e) { reject(e); }); })]; } }); }); }; Security.removeLoginState = function () { var url = window.location.href; var fragmentIndex = url.indexOf('#'); if (fragmentIndex !== -1) { var newURL = url.substring(0, fragmentIndex); window.history.replaceState({}, '', newURL); } }; Security.cleanUp = function (eventType, cid, closePopup) { if (closePopup === void 0) { closePopup = true; } if (Security.authenticatedListeners.has(eventType)) { window.removeEventListener('message', Security.authenticatedListeners.get(eventType)); Security.authenticatedListeners.delete(eventType); } if (eventType === EventTypes_1.EventTypes.CHECK_AUTHENTICATED) { var iframe = document.getElementById(Security.AUTH_IFRAME_ID); if (iframe) { iframe.remove(); } } else if (eventType === EventTypes_1.EventTypes.AUTHENTICATE) { if (closePopup) { if (Security.popupWindow && !Security.popupWindow.closed) { Security.popupWindow.close(); } delete Security.popupWindow; } } }; Security.authenticatedListeners = new Map(); Security.AUTH_IFRAME_ID = 'venly-auth-iframe'; Security.LOGOUT_IFRAME_ID = 'venly-logout-iframe'; Security.THIRD_PARTY_COOKIES_DISABLED = 'Third party cookies are disabled'; Security.initialiseAuthenticatedListener = function (clientId, eventType, cid, closePopup) { return tslib_1.__awaiter(this, void 0, void 0, function () { var _this = this; return tslib_1.__generator(this, function (_a) { return [2 /*return*/, new Promise(function (resolve, reject) { var newListener = function (message) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var auth, keycloakResult, initOptions, loginResult, loginResult, e_1; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (!(message && message.origin === Utils_1.default.urls.connect)) return [3 /*break*/, 11]; if (!(message.data && message.data.type === eventType)) return [3 /*break*/, 10]; auth = message.data; if (Security.isLoginPopupClosedInterval) { Security.clearIsLoginPopupClosedInterval(); } _a.label = 1; case 1: _a.trys.push([1, 9, , 10]); if (!auth.success) return [3 /*break*/, 5]; if (!auth.authenticated) return [3 /*break*/, 3]; Security.cleanUp(eventType, cid, closePopup); keycloakResult = auth.keycloak; initOptions = { onLoad: 'check-sso', token: keycloakResult.token, refreshToken: keycloakResult.refreshToken, idToken: keycloakResult.idToken, timeSkew: keycloakResult.timeSkew, checkLoginIframe: false, }; // Remove the login state from the URL when tokens are already present (the checkAuthenticated iframe already handled it) Security.removeLoginState(); return [4 /*yield*/, Security.initKeycloak(Security.getConfig(clientId), initOptions)]; case 2: loginResult = _a.sent(); resolve({ keycloak: loginResult.keycloak, authenticated: loginResult.authenticated, }); return [3 /*break*/, 4]; case 3: resolve({ authenticated: false }); _a.label = 4; case 4: return [3 /*break*/, 8]; case 5: if (!(auth.reason && auth.reason === Security.THIRD_PARTY_COOKIES_DISABLED)) return [3 /*break*/, 7]; return [4 /*yield*/, Security.initKeycloak(Security.getConfig(clientId), { onLoad: 'check-sso', checkLoginIframe: false })]; case 6: loginResult = _a.sent(); resolve({ keycloak: loginResult.keycloak, authenticated: loginResult.authenticated, }); return [3 /*break*/, 8]; case 7: reject({ error: auth.reason }); _a.label = 8; case 8: return [3 /*break*/, 10]; case 9: e_1 = _a.sent(); reject({ error: e_1 }); return [3 /*break*/, 10]; case 10: return [2 /*return*/, message]; case 11: return [2 /*return*/]; } }); }); }; window.addEventListener('message', newListener); if (Security.authenticatedListeners.has(eventType)) { window.removeEventListener('message', Security.authenticatedListeners.get(eventType)); } Security.authenticatedListeners.set(eventType, newListener); })]; }); }); }; Security.createLogoutListener = function (eventType, auth, resolve, reject) { return tslib_1.__awaiter(this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { return [2 /*return*/, function (message) { if (message && message.origin === Utils_1.default.urls.connect && message.data && message.data.type === eventType) { if (auth.authenticated) { if (!message.data.authenticated) { auth.onAuthLogout && auth.onAuthLogout(); resolve(); } else { reject(); } } else { resolve(); } } }]; }); }); }; return Security; }()); exports.Security = Security; //# sourceMappingURL=Security.js.map