diff --git a/lib/msal-browser/src/interaction_client/PopupClient.ts b/lib/msal-browser/src/interaction_client/PopupClient.ts index 2fd05de3c5..92010c882a 100644 --- a/lib/msal-browser/src/interaction_client/PopupClient.ts +++ b/lib/msal-browser/src/interaction_client/PopupClient.ts @@ -58,6 +58,7 @@ export type PopupParams = { export class PopupClient extends StandardInteractionClient { private currentWindow: Window | undefined; protected nativeStorage: BrowserCacheManager; + private authChannel: BroadcastChannel; constructor( config: BrowserConfiguration, @@ -85,6 +86,7 @@ export class PopupClient extends StandardInteractionClient { // Properly sets this reference for the unload event. this.unloadWindow = this.unloadWindow.bind(this); this.nativeStorage = nativeStorageImpl; + this.authChannel = new BroadcastChannel('auth'); } /** @@ -547,57 +549,19 @@ export class PopupClient extends StandardInteractionClient { ): Promise { return new Promise((resolve, reject) => { this.logger.verbose( - "PopupHandler.monitorPopupForHash - polling started" + "PopupHandler.monitorPopupForHash" ); - - const intervalId = setInterval(() => { - // Window is closed - if (popupWindow.closed) { - this.logger.error( - "PopupHandler.monitorPopupForHash - window closed" - ); - clearInterval(intervalId); - reject( - createBrowserAuthError( - BrowserAuthErrorCodes.userCancelled - ) - ); - return; - } - - let 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 = popupWindow.location.href; - } catch (e) {} - - // Don't process blank pages or cross domain - if (!href || href === "about:blank") { - return; - } - clearInterval(intervalId); - - let responseString = ""; - const responseType = - this.config.auth.OIDCOptions.serverResponseType; - if (popupWindow) { - if (responseType === ServerResponseType.QUERY) { - responseString = popupWindow.location.search; - } else { - responseString = popupWindow.location.hash; - } - } - - this.logger.verbose( - "PopupHandler.monitorPopupForHash - popup window is on same origin as caller" + this.authChannel.onmessage = function (event) { + resolve(event.data); + } + this.authChannel.onmessageerror = function (event) { + console.log('BroadcastChannel error', event.data); + reject( + createBrowserAuthError( + BrowserAuthErrorCodes.popupWindowError + ) ); - - resolve(responseString); - }, this.config.system.pollIntervalMilliseconds); + } }).finally(() => { this.cleanPopup(popupWindow, popupWindowParent); }); @@ -763,6 +727,9 @@ export class PopupClient extends StandardInteractionClient { // Close window. popupWindow.close(); + // Close the broadcast channel + this.authChannel.close(); + // Remove window unload function popupWindowParent.removeEventListener( "beforeunload", diff --git a/lib/msal-browser/src/interaction_client/RedirectClient.ts b/lib/msal-browser/src/interaction_client/RedirectClient.ts index abd01a3615..ce86f2c973 100644 --- a/lib/msal-browser/src/interaction_client/RedirectClient.ts +++ b/lib/msal-browser/src/interaction_client/RedirectClient.ts @@ -67,6 +67,7 @@ function getNavigationType(): NavigationTimingType | undefined { export class RedirectClient extends StandardInteractionClient { protected nativeStorage: BrowserCacheManager; + private authChannel = new BroadcastChannel('auth'); constructor( config: BrowserConfiguration, @@ -248,6 +249,9 @@ export class RedirectClient extends StandardInteractionClient { "Back navigation event detected. Muting no_server_response error" ); } + // Logout with popup case + this.authChannel.postMessage(""); + window.close(); return null; } @@ -394,7 +398,8 @@ export class RedirectClient extends StandardInteractionClient { ResponseHandler.validateInteractionType( response, this.browserCrypto, - InteractionType.Redirect + // TODO: Use correct type depending on the situation + InteractionType.Popup ); } catch (e) { if (e instanceof AuthError) { @@ -422,6 +427,11 @@ export class RedirectClient extends StandardInteractionClient { if (cachedHash) { response = UrlUtils.getDeserializedResponse(cachedHash); + + // Login with popup case + this.authChannel.postMessage(cachedHash); + window.close(); + if (response) { this.logger.verbose( "Hash does not contain known properties, returning cached hash"