UNPKG

msal

Version:
321 lines 12.5 kB
"use strict"; /* * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.WindowUtils = void 0; var ClientAuthError_1 = require("../error/ClientAuthError"); var UrlUtils_1 = require("./UrlUtils"); var Constants_1 = require("./Constants"); var TimeUtils_1 = require("./TimeUtils"); var WindowUtils = /** @class */ (function () { function WindowUtils() { } /** * @hidden * Checks if the current page is running in an iframe. * @ignore */ WindowUtils.isInIframe = function () { return window.parent !== window; }; /** * @hidden * Check if the current page is running in a popup. * @ignore */ WindowUtils.isInPopup = function () { return !!(window.opener && window.opener !== window); }; /** * @hidden * @param prefix * @param scopes * @param authority */ WindowUtils.generateFrameName = function (prefix, requestSignature) { return "" + prefix + Constants_1.Constants.resourceDelimiter + requestSignature; }; /** * @hidden * Polls an iframe until it loads a url with a hash * @ignore */ WindowUtils.monitorIframeForHash = function (contentWindow, timeout, urlNavigate, logger) { return new Promise(function (resolve, reject) { /* * Polling for iframes can be purely timing based, * since we don't need to account for interaction. */ var nowMark = TimeUtils_1.TimeUtils.relativeNowMs(); var timeoutMark = nowMark + timeout; logger.verbose("monitorWindowForIframe polling started"); var intervalId = setInterval(function () { if (TimeUtils_1.TimeUtils.relativeNowMs() > timeoutMark) { logger.error("monitorIframeForHash unable to find hash in url, timing out"); logger.errorPii("monitorIframeForHash polling timed out for url: " + urlNavigate); clearInterval(intervalId); reject(ClientAuthError_1.ClientAuthError.createTokenRenewalTimeoutError()); return; } var href; try { /* * Will throw if cross origin, * which should be caught and ignored * since we need the interval to keep running while on STS UI. */ href = contentWindow.location.href; } catch (e) { } if (href && UrlUtils_1.UrlUtils.urlContainsHash(href)) { logger.verbose("monitorIframeForHash found url in hash"); clearInterval(intervalId); resolve(contentWindow.location.hash); } }, WindowUtils.POLLING_INTERVAL_MS); }); }; /** * @hidden * Polls a popup until it loads a url with a hash * @ignore */ WindowUtils.monitorPopupForHash = function (contentWindow, timeout, urlNavigate, logger) { return new Promise(function (resolve, reject) { /* * Polling for popups needs to be tick-based, * since a non-trivial amount of time can be spent on interaction (which should not count against the timeout). */ var maxTicks = timeout / WindowUtils.POLLING_INTERVAL_MS; var ticks = 0; logger.verbose("monitorWindowForHash polling started"); var intervalId = setInterval(function () { if (contentWindow.closed) { logger.error("monitorWindowForHash window closed"); clearInterval(intervalId); reject(ClientAuthError_1.ClientAuthError.createUserCancelledError()); return; } var href; try { /* * Will throw if cross origin, * which should be caught and ignored * since we need the interval to keep running while on STS UI. */ href = contentWindow.location.href; } catch (e) { } // Don't process blank pages or cross domain if (!href || href === "about:blank") { return; } /* * Only run clock when we are on same domain for popups * as popup operations can take a long time. */ ticks++; if (href && UrlUtils_1.UrlUtils.urlContainsHash(href)) { logger.verbose("monitorPopupForHash found url in hash"); clearInterval(intervalId); var hash = contentWindow.location.hash; WindowUtils.clearUrlFragment(contentWindow); resolve(hash); } else if (ticks > maxTicks) { logger.error("monitorPopupForHash unable to find hash in url, timing out"); logger.errorPii("monitorPopupForHash polling timed out for url: " + urlNavigate); clearInterval(intervalId); reject(ClientAuthError_1.ClientAuthError.createTokenRenewalTimeoutError()); } }, WindowUtils.POLLING_INTERVAL_MS); }); }; /** * @hidden * Loads iframe with authorization endpoint URL * @ignore */ WindowUtils.loadFrame = function (urlNavigate, frameName, timeoutMs, logger) { var _this = this; /* * This trick overcomes iframe navigation in IE * IE does not load the page consistently in iframe */ logger.infoPii("LoadFrame: " + frameName); return new Promise(function (resolve, reject) { setTimeout(function () { var frameHandle = _this.loadFrameSync(urlNavigate, frameName, logger); if (!frameHandle) { reject("Unable to load iframe with name: " + frameName); return; } resolve(frameHandle); }, timeoutMs); }); }; /** * @hidden * Loads the iframe synchronously when the navigateTimeFrame is set to `0` * @param urlNavigate * @param frameName * @param logger */ WindowUtils.loadFrameSync = function (urlNavigate, frameName, logger) { var frameHandle = WindowUtils.addHiddenIFrame(frameName, logger); // returning to handle null in loadFrame, also to avoid null object access errors if (!frameHandle) { return null; } else if (frameHandle.src === "" || frameHandle.src === "about:blank") { frameHandle.src = urlNavigate; logger.infoPii("Frame Name : " + frameName + " Navigated to: " + urlNavigate); } return frameHandle; }; /** * @hidden * Adds the hidden iframe for silent token renewal. * @ignore */ WindowUtils.addHiddenIFrame = function (iframeId, logger) { if (typeof iframeId === "undefined") { return null; } logger.info("Add msal iframe to document"); logger.infoPii("Add msal frame to document:" + iframeId); var adalFrame = document.getElementById(iframeId); if (!adalFrame) { logger.verbose("Add msal iframe does not exist"); var ifr = document.createElement("iframe"); ifr.setAttribute("id", iframeId); ifr.setAttribute("aria-hidden", "true"); ifr.style.visibility = "hidden"; ifr.style.position = "absolute"; ifr.style.width = ifr.style.height = "0"; ifr.style.border = "0"; ifr.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms"); adalFrame = document.getElementsByTagName("body")[0].appendChild(ifr); } else { logger.verbose("Add msal iframe already exists"); } return adalFrame; }; /** * @hidden * Removes a hidden iframe from the page. * @ignore */ WindowUtils.removeHiddenIframe = function (iframe) { if (document.body === iframe.parentNode) { document.body.removeChild(iframe); } }; /** * @hidden * Find and return the iframe element with the given hash * @ignore */ WindowUtils.getIframeWithHash = function (hash) { var iframes = document.getElementsByTagName("iframe"); var iframeArray = Array.apply(null, Array(iframes.length)).map(function (iframe, index) { return iframes.item(index); }); // eslint-disable-line prefer-spread return iframeArray.filter(function (iframe) { try { return iframe.contentWindow.location.hash === hash; } catch (e) { return false; } })[0]; }; /** * @hidden * Returns an array of all the popups opened by MSAL * @ignore */ WindowUtils.getPopups = function () { if (!window.openedWindows) { window.openedWindows = []; } return window.openedWindows; }; /** * @hidden * Find and return the popup with the given hash * @ignore */ WindowUtils.getPopUpWithHash = function (hash) { return WindowUtils.getPopups().filter(function (popup) { try { return popup.location.hash === hash; } catch (e) { return false; } })[0]; }; /** * @hidden * Add the popup to the known list of popups * @ignore */ WindowUtils.trackPopup = function (popup) { WindowUtils.getPopups().push(popup); }; /** * @hidden * Close all popups * @ignore */ WindowUtils.closePopups = function () { WindowUtils.getPopups().forEach(function (popup) { return popup.close(); }); }; /** * @ignore * * blocks any login/acquireToken calls to reload from within a hidden iframe (generated for silent calls) */ WindowUtils.blockReloadInHiddenIframes = function () { // return an error if called from the hidden iframe created by the msal js silent calls if (UrlUtils_1.UrlUtils.urlContainsHash(window.location.hash) && WindowUtils.isInIframe()) { throw ClientAuthError_1.ClientAuthError.createBlockTokenRequestsInHiddenIframeError(); } }; /** * * @param cacheStorage */ WindowUtils.checkIfBackButtonIsPressed = function (cacheStorage) { var redirectCache = cacheStorage.getItem(Constants_1.TemporaryCacheKeys.REDIRECT_REQUEST); // if redirect request is set and there is no hash if (redirectCache && !UrlUtils_1.UrlUtils.urlContainsHash(window.location.hash)) { var splitCache = redirectCache.split(Constants_1.Constants.resourceDelimiter); splitCache.shift(); var state = splitCache.length > 0 ? splitCache.join(Constants_1.Constants.resourceDelimiter) : null; cacheStorage.resetTempCacheItems(state); } }; /** * Removes url fragment from browser url */ WindowUtils.clearUrlFragment = function (contentWindow) { contentWindow.location.hash = ""; // Office.js sets history.replaceState to null if (typeof contentWindow.history.replaceState === "function") { // Full removes "#" from url contentWindow.history.replaceState(null, null, "" + contentWindow.location.pathname + contentWindow.location.search); } }; /** * @hidden * Interval in milliseconds that we poll a window * @ignore */ WindowUtils.POLLING_INTERVAL_MS = 50; return WindowUtils; }()); exports.WindowUtils = WindowUtils; //# sourceMappingURL=WindowUtils.js.map