@brionmario-experimental/asgardeo-auth-spa
Version:
Asgardeo Auth SPA SDK to be used in Single-Page Applications.
252 lines • 13.1 kB
JavaScript
/**
* Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
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) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { AsgardeoAuthClient, SESSION_STATE } from "@asgardeo/auth-js";
import { CHECK_SESSION_SIGNED_IN, CHECK_SESSION_SIGNED_OUT, INITIALIZED_SILENT_SIGN_IN, OP_IFRAME, PROMPT_NONE_IFRAME, RP_IFRAME, SET_SESSION_STATE_FROM_IFRAME, SILENT_SIGN_IN_STATE, STATE, STATE_QUERY, Storage } from "../constants";
import { SPAUtils } from "../utils";
export const SessionManagementHelper = (() => {
let _clientID;
let _checkSessionEndpoint;
let _sessionState;
let _interval;
let _redirectURL;
let _sessionRefreshInterval;
let _signOut;
let _sessionRefreshIntervalTimeout;
let _checkSessionIntervalTimeout;
let _storage;
let _setSessionState;
let _getAuthorizationURL;
const initialize = (clientID, checkSessionEndpoint, getSessionState, interval, sessionRefreshInterval, redirectURL, getAuthorizationURL) => {
_clientID = clientID;
_checkSessionEndpoint = checkSessionEndpoint;
_sessionState = getSessionState;
_interval = interval;
_redirectURL = redirectURL;
_sessionRefreshInterval = sessionRefreshInterval;
_getAuthorizationURL = getAuthorizationURL;
if (_interval > -1) {
initiateCheckSession();
}
if (_sessionRefreshInterval > -1) {
sessionRefreshInterval = setInterval(() => {
sendPromptNoneRequest();
}, _sessionRefreshInterval * 1000);
}
};
const initiateCheckSession = () => __awaiter(void 0, void 0, void 0, function* () {
var _a;
if (!_checkSessionEndpoint || !_clientID || !_redirectURL) {
return;
}
const OP_IFRAME = "opIFrame";
function checkSession() {
var _a;
return __awaiter(this, void 0, void 0, function* () {
const sessionState = yield _sessionState();
if (Boolean(_clientID) && Boolean(sessionState)) {
const message = `${_clientID} ${sessionState}`;
const rpIFrame = document.getElementById(RP_IFRAME);
const opIframe = (_a = rpIFrame === null || rpIFrame === void 0 ? void 0 : rpIFrame.contentDocument) === null || _a === void 0 ? void 0 : _a.getElementById(OP_IFRAME);
const win = opIframe.contentWindow;
win === null || win === void 0 ? void 0 : win.postMessage(message, _checkSessionEndpoint);
}
});
}
const rpIFrame = document.getElementById(RP_IFRAME);
const opIframe = (_a = rpIFrame === null || rpIFrame === void 0 ? void 0 : rpIFrame.contentDocument) === null || _a === void 0 ? void 0 : _a.getElementById(OP_IFRAME);
opIframe.src = _checkSessionEndpoint + "?client_id=" + _clientID + "&redirect_uri=" + _redirectURL;
_checkSessionIntervalTimeout = setInterval(checkSession, _interval * 1000);
listenToResponseFromOPIFrame();
});
/**
* Destroys session intervals.
*/
const reset = () => {
clearInterval(_checkSessionIntervalTimeout);
clearInterval(_sessionRefreshIntervalTimeout);
};
const listenToResponseFromOPIFrame = () => {
function receiveMessage(e) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
const targetOrigin = _checkSessionEndpoint;
if (!targetOrigin
|| (targetOrigin === null || targetOrigin === void 0 ? void 0 : targetOrigin.indexOf(e.origin)) < 0
|| ((_a = e === null || e === void 0 ? void 0 : e.data) === null || _a === void 0 ? void 0 : _a.type) === SET_SESSION_STATE_FROM_IFRAME) {
return;
}
if (e.data === "unchanged") {
// [RP] session state has not changed
}
else if (e.data === "error") {
window.location.href = yield _signOut();
}
else if (e.data === "changed") {
// [RP] session state has changed. Sending prompt=none request...
sendPromptNoneRequest();
}
});
}
window === null || window === void 0 ? void 0 : window.addEventListener("message", receiveMessage, false);
};
const sendPromptNoneRequest = () => __awaiter(void 0, void 0, void 0, function* () {
var _b;
const rpIFrame = document.getElementById(RP_IFRAME);
const promptNoneIFrame = (_b = rpIFrame === null || rpIFrame === void 0 ? void 0 : rpIFrame.contentDocument) === null || _b === void 0 ? void 0 : _b.getElementById(PROMPT_NONE_IFRAME);
if (SPAUtils.canSendPromptNoneRequest()) {
SPAUtils.setPromptNoneRequestSent(true);
const receiveMessageListener = (e) => {
var _a, _b, _c;
if (((_a = e === null || e === void 0 ? void 0 : e.data) === null || _a === void 0 ? void 0 : _a.type) === SET_SESSION_STATE_FROM_IFRAME) {
_setSessionState((_c = (_b = e === null || e === void 0 ? void 0 : e.data) === null || _b === void 0 ? void 0 : _b.data) !== null && _c !== void 0 ? _c : "");
window === null || window === void 0 ? void 0 : window.removeEventListener("message", receiveMessageListener);
}
};
if (_storage === Storage.BrowserMemory || _storage === Storage.WebWorker) {
window === null || window === void 0 ? void 0 : window.addEventListener("message", receiveMessageListener);
}
const promptNoneURL = yield _getAuthorizationURL({
prompt: "none",
response_mode: "query",
state: STATE
});
promptNoneIFrame.src = promptNoneURL;
}
});
/**
* This contains the logic to process the response of a prompt none request.
*
* @param setSessionState The method that sets the session state.
* on the output of the content of the redirect URL
*/
const receivePromptNoneResponse = (setSessionState) => __awaiter(void 0, void 0, void 0, function* () {
var _c, _d;
const state = new URL(window.location.href).searchParams.get(STATE_QUERY);
const sessionState = new URL(window.location.href).searchParams.get(SESSION_STATE);
const parent = window.parent.parent;
if (state !== null && (state.includes(STATE) || state.includes(SILENT_SIGN_IN_STATE))) {
// Prompt none response.
const code = new URL(window.location.href).searchParams.get("code");
if (code !== null && code.length !== 0) {
if (state.includes(SILENT_SIGN_IN_STATE)) {
const message = {
data: {
code,
sessionState: sessionState !== null && sessionState !== void 0 ? sessionState : "",
state
},
type: CHECK_SESSION_SIGNED_IN
};
sessionStorage.setItem(INITIALIZED_SILENT_SIGN_IN, "false");
parent.postMessage(message, parent.origin);
SPAUtils.setPromptNoneRequestSent(false);
window.location.href = "about:blank";
yield SPAUtils.waitTillPageRedirect();
return true;
}
const newSessionState = new URL(window.location.href).searchParams.get("session_state");
if (_storage === Storage.LocalStorage || _storage === Storage.SessionStorage) {
setSessionState && (yield setSessionState(newSessionState));
}
else {
const message = {
data: newSessionState !== null && newSessionState !== void 0 ? newSessionState : "",
type: SET_SESSION_STATE_FROM_IFRAME
};
(_d = (_c = window === null || window === void 0 ? void 0 : window.parent) === null || _c === void 0 ? void 0 : _c.parent) === null || _d === void 0 ? void 0 : _d.postMessage(message);
}
SPAUtils.setPromptNoneRequestSent(false);
window.location.href = "about:blank";
yield SPAUtils.waitTillPageRedirect();
return true;
}
else {
if (state.includes(SILENT_SIGN_IN_STATE)) {
const message = {
type: CHECK_SESSION_SIGNED_OUT
};
window.parent.parent.postMessage(message, parent.origin);
SPAUtils.setPromptNoneRequestSent(false);
window.location.href = "about:blank";
yield SPAUtils.waitTillPageRedirect();
return true;
}
SPAUtils.setPromptNoneRequestSent(false);
const signOutURL = yield _signOut();
// Clearing user session data before redirecting to the signOutURL because user has been already logged
// out by the initial logout request in the single logout flow.
yield AsgardeoAuthClient.clearUserSessionData();
parent.location.href = signOutURL;
window.location.href = "about:blank";
yield SPAUtils.waitTillPageRedirect();
return true;
}
}
return false;
});
return (signOut, storage, setSessionState) => __awaiter(void 0, void 0, void 0, function* () {
var _e;
let rpIFrame = document.createElement("iframe");
rpIFrame.setAttribute("id", RP_IFRAME);
rpIFrame.style.display = "none";
let rpIframeLoaded = false;
rpIFrame.onload = () => {
var _a, _b, _c, _d;
rpIFrame = document.getElementById(RP_IFRAME);
const rpDoc = rpIFrame === null || rpIFrame === void 0 ? void 0 : rpIFrame.contentDocument;
const opIFrame = rpDoc === null || rpDoc === void 0 ? void 0 : rpDoc.createElement("iframe");
if (opIFrame) {
opIFrame.setAttribute("id", OP_IFRAME);
opIFrame.style.display = "none";
}
const promptNoneIFrame = rpDoc === null || rpDoc === void 0 ? void 0 : rpDoc.createElement("iframe");
if (promptNoneIFrame) {
promptNoneIFrame.setAttribute("id", PROMPT_NONE_IFRAME);
promptNoneIFrame.style.display = "none";
}
opIFrame && ((_b = (_a = rpIFrame === null || rpIFrame === void 0 ? void 0 : rpIFrame.contentDocument) === null || _a === void 0 ? void 0 : _a.body) === null || _b === void 0 ? void 0 : _b.appendChild(opIFrame));
promptNoneIFrame && ((_d = (_c = rpIFrame === null || rpIFrame === void 0 ? void 0 : rpIFrame.contentDocument) === null || _c === void 0 ? void 0 : _c.body) === null || _d === void 0 ? void 0 : _d.appendChild(promptNoneIFrame));
rpIframeLoaded = true;
};
(_e = document === null || document === void 0 ? void 0 : document.body) === null || _e === void 0 ? void 0 : _e.appendChild(rpIFrame);
_signOut = signOut;
_storage = storage;
_setSessionState = setSessionState;
const sleep = () => {
return new Promise((resolve) => setTimeout(resolve, 1));
};
while (rpIframeLoaded === false) {
yield sleep();
}
return {
initialize,
receivePromptNoneResponse,
reset
};
});
})();
//# sourceMappingURL=session-management-helper.js.map