{"version":3,"file":"SilentHandler.js","sources":["../../src/interaction_handler/SilentHandler.ts"],"sourcesContent":["/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { UrlString, StringUtils, CommonAuthorizationCodeRequest, AuthorizationCodeClient, Constants, Logger } from \"@azure/msal-common\";\nimport { InteractionHandler } from \"./InteractionHandler\";\nimport { BrowserAuthError } from \"../error/BrowserAuthError\";\nimport { BrowserCacheManager } from \"../cache/BrowserCacheManager\";\nimport { BrowserSystemOptions, DEFAULT_IFRAME_TIMEOUT_MS } from \"../config/Configuration\";\n\nexport class SilentHandler extends InteractionHandler {\n\n private navigateFrameWait: number;\n private pollIntervalMilliseconds: number;\n\n constructor(authCodeModule: AuthorizationCodeClient, storageImpl: BrowserCacheManager, authCodeRequest: CommonAuthorizationCodeRequest, logger: Logger, systemOptions: Required>) {\n super(authCodeModule, storageImpl, authCodeRequest, logger);\n this.navigateFrameWait = systemOptions.navigateFrameWait;\n this.pollIntervalMilliseconds = systemOptions.pollIntervalMilliseconds;\n }\n\n /**\n * Creates a hidden iframe to given URL using user-requested scopes as an id.\n * @param urlNavigate\n * @param userRequestScopes\n */\n async initiateAuthRequest(requestUrl: string): Promise {\n if (StringUtils.isEmpty(requestUrl)) {\n // Throw error if request URL is empty.\n this.logger.info(\"Navigate url is empty\");\n throw BrowserAuthError.createEmptyNavigationUriError();\n }\n\n return this.navigateFrameWait ? await this.loadFrame(requestUrl) : this.loadFrameSync(requestUrl);\n }\n\n /**\n * Monitors an iframe content window until it loads a url with a known hash, or hits a specified timeout.\n * @param iframe\n * @param timeout\n */\n monitorIframeForHash(iframe: HTMLIFrameElement, timeout: number): Promise {\n return new Promise((resolve, reject) => {\n if (timeout < DEFAULT_IFRAME_TIMEOUT_MS) {\n this.logger.warning(`system.loadFrameTimeout or system.iframeHashTimeout set to lower (${timeout}ms) than the default (${DEFAULT_IFRAME_TIMEOUT_MS}ms). This may result in timeouts.`);\n }\n\n /*\n * Polling for iframes can be purely timing based,\n * since we don't need to account for interaction.\n */\n const nowMark = window.performance.now();\n const timeoutMark = nowMark + timeout;\n\n const intervalId = setInterval(() => {\n if (window.performance.now() > timeoutMark) {\n this.removeHiddenIframe(iframe);\n clearInterval(intervalId);\n reject(BrowserAuthError.createMonitorIframeTimeoutError());\n return;\n }\n\n let href: string = Constants.EMPTY_STRING;\n const contentWindow = iframe.contentWindow;\n try {\n /*\n * Will throw if cross origin,\n * which should be caught and ignored\n * since we need the interval to keep running while on STS UI.\n */\n href = contentWindow ? contentWindow.location.href : Constants.EMPTY_STRING;\n } catch (e) {}\n\n if (StringUtils.isEmpty(href)) {\n return;\n }\n\n const contentHash = contentWindow ? contentWindow.location.hash: Constants.EMPTY_STRING;\n if (UrlString.hashContainsKnownProperties(contentHash)) {\n // Success case\n this.removeHiddenIframe(iframe);\n clearInterval(intervalId);\n resolve(contentHash);\n return;\n }\n }, this.pollIntervalMilliseconds);\n });\n }\n\n /**\n * @hidden\n * Loads iframe with authorization endpoint URL\n * @ignore\n */\n private loadFrame(urlNavigate: string): Promise {\n /*\n * This trick overcomes iframe navigation in IE\n * IE does not load the page consistently in iframe\n */\n\n return new Promise((resolve, reject) => {\n const frameHandle = this.createHiddenIframe();\n\n setTimeout(() => {\n if (!frameHandle) {\n reject(\"Unable to load iframe\");\n return;\n }\n\n frameHandle.src = urlNavigate;\n\n resolve(frameHandle);\n }, this.navigateFrameWait);\n });\n }\n\n /**\n * @hidden\n * Loads the iframe synchronously when the navigateTimeFrame is set to `0`\n * @param urlNavigate\n * @param frameName\n * @param logger\n */\n private loadFrameSync(urlNavigate: string): HTMLIFrameElement{\n const frameHandle = this.createHiddenIframe();\n\n frameHandle.src = urlNavigate;\n\n return frameHandle;\n }\n\n /**\n * @hidden\n * Creates a new hidden iframe or gets an existing one for silent token renewal.\n * @ignore\n */\n private createHiddenIframe(): HTMLIFrameElement {\n const authFrame = document.createElement(\"iframe\");\n\n authFrame.style.visibility = \"hidden\";\n authFrame.style.position = \"absolute\";\n authFrame.style.width = authFrame.style.height = \"0\";\n authFrame.style.border = \"0\";\n authFrame.setAttribute(\"sandbox\", \"allow-scripts allow-same-origin allow-forms\");\n document.getElementsByTagName(\"body\")[0].appendChild(authFrame);\n\n return authFrame;\n }\n\n /**\n * @hidden\n * Removes a hidden iframe from the page.\n * @ignore\n */\n private removeHiddenIframe(iframe: HTMLIFrameElement): void {\n if (document.body === iframe.parentNode) {\n document.body.removeChild(iframe);\n }\n }\n}\n"],"names":[],"mappings":"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"}