web.config change

This commit is contained in:
Bikram Choudhury
2026-05-07 16:14:41 +05:30
parent 748702f237
commit 8e6e836d14
2 changed files with 54 additions and 9 deletions
+15 -9
View File
@@ -147,18 +147,20 @@ export async function acquireMsalTokenForAccount(
});
}
}
// For Mooncake, popups to login.partner.microsoftonline.cn are blocked by COOP headers
// (ERR_BLOCKED_BY_RESPONSE). Use loginRedirect instead for interactive sign-in.
// Silent attempts (prompt: "none") are skipped on Mooncake for the same reason —
// ssoSilent already failed above, so there is nothing more to try silently.
// For Mooncake, popups to login.partner.microsoftonline.cn are blocked by COOP headers.
// Use loginRedirect when running standalone (not in an iframe) so the top-level page can
// navigate away and return. Inside a portal iframe, redirect is forbidden by MSAL
// (redirect_in_iframe), so we fall back to loginPopup — MSAL v5's redirect bridge
// handles COOP via BroadcastChannel rather than window.opener, so the popup still works.
const isMooncake = configContext.AAD_ENDPOINT === Constants.AadEndpoints.Mooncake;
if (isMooncake) {
const isInIframe = window !== window.parent;
if (isMooncake && !isInIframe) {
if (silent) {
// ssoSilent already failed; a prompt:none popup would also be blocked on Mooncake.
// ssoSilent already failed; a redirect cannot be used silently.
// Re-throw so the caller knows silent acquisition was not possible.
throw new Error("Silent login not possible on Mooncake; interactive sign-in required.");
}
// Interactive: navigate the browser to the Mooncake AAD login page.
// Standalone (hosted explorer): navigate the page to the Mooncake AAD login URL.
// On return, handleRedirectPromise() in getMsalInstance() will cache the token.
await msalInstance.loginRedirect({ prompt: "login", ...loginRequest });
// Browser has navigated away; this line is never reached.
@@ -211,12 +213,16 @@ export async function acquireTokenWithMsal(
} catch (silentError) {
if (silentError instanceof msal.InteractionRequiredAuthError && silent === false) {
// Sovereign cloud environments (e.g., Azure China / Mooncake) block popups in some
// browser configurations. Use redirect-based flow instead to ensure compatibility.
// browser configurations. Use redirect-based flow instead when running standalone.
// Detection is based on configContext.AAD_ENDPOINT (set from the portal's serverId message
// via updateAADEndpoints), NOT window.location.host — the latter is unreliable when running
// the explorer locally (localhost) embedded inside portal.azure.cn.
// Inside a portal iframe, redirect is forbidden by MSAL (redirect_in_iframe error), so
// we fall back to acquireTokenPopup — MSAL v5's redirect bridge handles COOP via
// BroadcastChannel (not window.opener) so the popup works even from within an iframe.
const isMooncake = configContext.AAD_ENDPOINT === Constants.AadEndpoints.Mooncake;
if (isMooncake) {
const isInIframe = window !== window.parent;
if (isMooncake && !isInIframe) {
try {
// acquireTokenRedirect navigates the browser away; execution does not continue
// past this await. On return, getMsalInstance()'s handleRedirectPromise() will
+39
View File
@@ -65,6 +65,45 @@
</staticContent>
</system.webServer>
</location>
<!--
MSAL v5 redirect bridge requirements (https://aka.ms/msal.js/redirect-bridge):
1. Must NOT be served with Cross-Origin-Opener-Policy headers. If COOP is present on
the bridge page, the browser performs a browsing context group swap that severs the
BroadcastChannel communication channel back to the main application, causing
ERR_BLOCKED_BY_RESPONSE when the popup navigates to the AAD login endpoint.
The <remove> tag strips any COOP header added by Azure infrastructure globally.
The explicit unsafe-none value ensures no COOP is present even after clearing.
2. Must be served with Cache-Control: no-store. The bridge page carries auth codes
and tokens in its URL — caching by a CDN or proxy would expose those credentials.
-->
<location path="redirectBridge.html">
<system.webServer>
<staticContent>
<clientCache cacheControlMode="DisableCache" />
</staticContent>
<httpProtocol>
<customHeaders>
<remove name="Cross-Origin-Opener-Policy" />
<add name="Cross-Origin-Opener-Policy" value="unsafe-none" />
<add name="Cache-Control" value="no-store" />
</customHeaders>
</httpProtocol>
</system.webServer>
</location>
<location path="mpac/redirectBridge.html">
<system.webServer>
<staticContent>
<clientCache cacheControlMode="DisableCache" />
</staticContent>
<httpProtocol>
<customHeaders>
<remove name="Cross-Origin-Opener-Policy" />
<add name="Cross-Origin-Opener-Policy" value="unsafe-none" />
<add name="Cache-Control" value="no-store" />
</customHeaders>
</httpProtocol>
</system.webServer>
</location>
<location path="mpac/explorer.html">
<system.webServer>
<staticContent>