@venly/connect
Version:
Venly Connect SDK
466 lines • 23.2 kB
JavaScript
;
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