diff --git a/src/Utils/AuthorizationUtils.test.ts b/src/Utils/AuthorizationUtils.test.ts index 993b6b166..6eb5f761f 100644 --- a/src/Utils/AuthorizationUtils.test.ts +++ b/src/Utils/AuthorizationUtils.test.ts @@ -163,4 +163,42 @@ describe("AuthorizationUtils", () => { expect((instance as any)._config.auth.redirectUri).toBe("http://localhost/redirectBridge.html"); }); }); + + describe("getRedirectBridgeUrl()", () => { + const originalNodeEnv = process.env.NODE_ENV; + const originalPathname = window.location.pathname; + + afterEach(() => { + process.env.NODE_ENV = originalNodeEnv; + Object.defineProperty(window, "location", { + value: { ...window.location, pathname: originalPathname }, + writable: true, + }); + }); + + it("should use dev URL in development mode", () => { + process.env.NODE_ENV = "development"; + expect(AuthorizationUtils.getRedirectBridgeUrl()).toBe( + "https://dataexplorer-dev.azurewebsites.net/redirectBridge.html", + ); + }); + + it("should use MPAC path when on /mpac/", () => { + process.env.NODE_ENV = "production"; + Object.defineProperty(window, "location", { + value: { origin: "https://cosmos.azure.com", pathname: "/mpac/explorer.html" }, + writable: true, + }); + expect(AuthorizationUtils.getRedirectBridgeUrl()).toBe("https://cosmos.azure.com/mpac/redirectBridge.html"); + }); + + it("should use root path when not on /mpac/", () => { + process.env.NODE_ENV = "production"; + Object.defineProperty(window, "location", { + value: { origin: "https://cosmos.azure.com", pathname: "/explorer.html" }, + writable: true, + }); + expect(AuthorizationUtils.getRedirectBridgeUrl()).toBe("https://cosmos.azure.com/redirectBridge.html"); + }); + }); }); diff --git a/src/Utils/AuthorizationUtils.ts b/src/Utils/AuthorizationUtils.ts index 14fd7c04c..21bd23195 100644 --- a/src/Utils/AuthorizationUtils.ts +++ b/src/Utils/AuthorizationUtils.ts @@ -50,12 +50,25 @@ export function decryptJWTToken(token: string) { return JSON.parse(tokenPayload); } +export function getRedirectBridgeUrl(): string { + if (process.env.NODE_ENV === "development") { + return "https://dataexplorer-dev.azurewebsites.net/redirectBridge.html"; + } + const basePath = window.location.pathname.startsWith("/mpac/") ? "/mpac" : ""; + return `${window.location.origin}${basePath}/redirectBridge.html`; +} + +export function getPostLogoutRedirectUrl(): string { + if (process.env.NODE_ENV === "development") { + return "https://dataexplorer-dev.azurewebsites.net/hostedExplorer.html"; + } + const basePath = window.location.pathname.startsWith("/mpac/") ? "/mpac" : ""; + return `${window.location.origin}${basePath}`; +} + export async function getMsalInstance() { // Compute the redirect bridge URL for MSAL v5 COOP handling - const redirectBridgeUrl = - process.env.NODE_ENV === "development" - ? "https://dataexplorer-dev.azurewebsites.net/redirectBridge.html" - : `${window.location.origin}/redirectBridge.html`; + const redirectBridgeUrl = getRedirectBridgeUrl(); const msalConfig: msal.Configuration = { cache: { diff --git a/src/hooks/useAADAuth.ts b/src/hooks/useAADAuth.ts index 062455793..7a5bd2086 100644 --- a/src/hooks/useAADAuth.ts +++ b/src/hooks/useAADAuth.ts @@ -2,7 +2,12 @@ import * as msal from "@azure/msal-browser"; import { useBoolean } from "@fluentui/react-hooks"; import * as React from "react"; import { ConfigContext } from "../ConfigContext"; -import { acquireTokenWithMsal, getMsalInstance } from "../Utils/AuthorizationUtils"; +import { + acquireTokenWithMsal, + getMsalInstance, + getPostLogoutRedirectUrl, + getRedirectBridgeUrl, +} from "../Utils/AuthorizationUtils"; const cachedTenantId = localStorage.getItem("cachedTenantId"); @@ -59,10 +64,7 @@ export function useAADAuth(config?: ConfigContext): ReturnType { return; } // Use redirect bridge for MSAL v5 COOP handling - const redirectBridgeUrl = - process.env.NODE_ENV === "development" - ? "https://dataexplorer-dev.azurewebsites.net/redirectBridge.html" - : `${window.location.origin}/redirectBridge.html`; + const redirectBridgeUrl = getRedirectBridgeUrl(); try { const response = await msalInstance.loginPopup({ @@ -87,10 +89,7 @@ export function useAADAuth(config?: ConfigContext): ReturnType { setLoggedOut(); localStorage.removeItem("cachedTenantId"); // Redirect back to the hosted explorer after logout - const postLogoutRedirectUri = - process.env.NODE_ENV === "development" - ? "https://dataexplorer-dev.azurewebsites.net/hostedExplorer.html" - : `${window.location.origin}`; + const postLogoutRedirectUri = getPostLogoutRedirectUrl(); msalInstance.logoutRedirect({ postLogoutRedirectUri }); }, [msalInstance]); @@ -100,10 +99,7 @@ export function useAADAuth(config?: ConfigContext): ReturnType { return; } // Use redirect bridge for MSAL v5 COOP handling - const redirectBridgeUrl = - process.env.NODE_ENV === "development" - ? "https://dataexplorer-dev.azurewebsites.net/redirectBridge.html" - : `${window.location.origin}/redirectBridge.html`; + const redirectBridgeUrl = getRedirectBridgeUrl(); try { const response = await msalInstance.loginPopup({ redirectUri: redirectBridgeUrl,