Verwenden von MSAL in iframed-Apps

Standardmäßig verhindert MSAL, dass Vollframeumleitungen an Microsoft Entra ID Authentifizierungsendpunkt gesendet werden, wenn eine App in einem iFrame gerendert wird. Dies bedeutet, dass Sie keine Umleitungs-APIs für die Benutzerinteraktion mit dem IdP verwenden können:

  • Diese Einschränkung gilt, da Microsoft Entra ID jede Eingabeaufforderung, die eine Benutzerinteraktion erfordert (z. B. Eingabe von Anmeldeinformationen, Einwilligung, Abmelden usw.), nicht in einem iFrame rendert und stattdessen den X-FRAME OPTIONS SET TO DENYFehler auslöst – eine Maßnahme, die zum Schutz vor Clickjacking-Angriffen ergriffen wurde.
  • Stattdessen müssen Sie MSALs Popup-APIs verwenden, wenn eine Benutzerinteraktion erforderlich ist, und/oder die stillen APIs (ssoSilent(), acquireTokenSilent()), wenn eine Benutzerinteraktion vermieden werden kann.
  • Ebenso müssen Sie zum Abmelden die logoutPopup()-API verwenden (:warning: Wenn Ihre App eine Version von msal-browser verwendet, die älter als v2.13 ist, führen Sie unbedingt ein Upgrade durch und ersetzen Sie die logout()-API, da sie andernfalls eine vollständige Frame-Umleitung zu Microsoft Entra ID versucht).
  • Bei Verwendung von Popup-APIs müssen Sie alle Von der übergeordneten App auferlegten Sandboxing-Einschränkungen berücksichtigen. Insbesondere muss die übergeordnete App die allow-popups-Kennzeichnung setzen, wenn das iframe in einer Sandbox ausgeführt wird.

Azure AD B2C bietet eine eingebettete Anmeldeoberfläche, die das Rendern einer benutzerdefinierten Anmeldebenutzeroberfläche in einem iframe ermöglicht. Da MSAL die Umleitung in iframes standardmäßig verhindert, müssen Sie die Konfigurationsoption allowRedirectInIframe auf "true " festlegen, um dieses Feature verwenden zu können. Beachten Sie, dass das Aktivieren dieser Option für Apps auf Microsoft Entra ID aufgrund der oben genannten Einschränkung nicht empfohlen wird.

Browsereinschränkungen

Da Microsoft Entra-Sitzungscookies innerhalb eines Iframes als Drittanbietercookies gelten, blockieren oder löschen bestimmte Browser (z. B. Safari oder Chrome im Inkognito-Modus) diese standardmäßig. Dies wirkt sich auf die Einmalige Anmeldung für iframed-Apps aus, da sie keinen Zugriff auf die Sitzungscookies von IdP haben (siehe: Einmaliges Anmelden).

Außerdem haben in Chrome eingebettete MSAL-Apps keinen Zugriff auf den lokalen Speicher oder Sitzungsspeicher, wenn Drittanbieter-Cookies deaktiviert sind. MSAL wird in diesem Fall auf In-Memory-Speicher zurückgreifen.

Einmaliges Anmelden

Sie könnenSingle Sign-on zwischen iframed- und übergeordneten Apps mit demselben Ursprung und mit verschiedenem Ursprung erreichen, wenn Sie einen Kontohinweis von der übergeordneten App an die iframed-App übergeben.

Apps mit demselben Ursprung

Iframed- und übergeordnete Apps mit demselben Ursprung haben möglicherweise Zugriff auf dieselbe MSAL.js Cacheinstanz und können sich ohne Eingabeaufforderung anmelden, vorausgesetzt, dass beide Apps MSAL für die Verwendung des lokalen Speichers für die Zwischenspeicherung konfigurieren. Weitere Informationen finden Sie unter: Einmaliges Anmelden mit MSAL.js

Apps mit ursprungsübergreifendem Ursprung

Iframed- und übergeordnete Apps mit verschiedenem Ursprung können die ssoSilent() -API verwenden, um Single Sign-on zu erzielen. Dazu sollte die übergeordnete App entweder ein Konto, einen LoginHint (Benutzername) oder eine Sitzungs-ID (SID) an die iframed-App übergeben.

Apps können versuchen, ssoSilent ohne einen der oben genannten Parameter zu verwenden. Beachten Sie jedoch, dass es zusätzliche Aspekte gibt, wenn Sie ssoSilent verwenden, ohne Informationen über die Sitzung des Benutzers anzugeben.

Für die ursprungsübergreifende Kommunikation zwischen iframed- und übergeordneten Apps gibt es einige Alternativen, die Sie berücksichtigen können:

  • Sie können in der übergeordneten App Abfrageparameter zur Quelle des iFrames hinzufügen und sie später im untergeordneten iFrame abrufen:
// Create the main myMSALObj instance
// configuration parameters are located at authConfig.js
const myMSALObj = new msal.PublicClientApplication({
    auth: {
        clientId: "ENTER_CLIENT_ID",
        authority: "https://login.microsoftonline.com/ENTER_TENANT_ID",
        redirectUri: "/redirect", // set to a blank page for handling auth code response via popups
    },
    cache: {
        cacheLocation: "localStorage", // set your cache location to local storage
    },
});

window.onload = () => {
    
    const urlParams = new URLSearchParams(window.location.search);
    const sid = urlParams.get("sid");

    // attempt SSO
    myMSALObj.ssoSilent({
        sid: sid
    }).then((response) => {
        // do something with response
    }).catch(error => {
        // handle errors
    });
}
  • Sie können die postMessage()-API in der übergeordneten App verwenden und in der untergeordneten App auf Nachrichtenereignisse warten:
// Create the main myMSALObj instance
// configuration parameters are located at authConfig.js
const myMSALObj = new msal.PublicClientApplication({
    auth: {
        clientId: "ENTER_CLIENT_ID",
        authority: "https://login.microsoftonline.com/ENTER_TENANT_ID",
        redirectUri: "/redirect", // set to a blank page for handling auth code response via popups
    },
    cache: {
        cacheLocation: "localStorage", // set your cache location to local storage
    },
});

const parentDomain = "http://localhost:3001";

window.addEventListener("message", (event) => {
    // check the origin of the data
    if (event.origin === parentDomain) {
        const sid = event.data;

        // attempt SSO
        myMSALObj.ssoSilent({
            sid: sid
        }).then((response) => {
            // do something with response
        }).catch(error => {
            // handle errors
        });
    }
});

Fehlerbehandlung

Sie sollten alle Fehler abfangen und behandeln, wenn ssoSilent() fehlschlägt. Dies gilt insbesondere für:

  • InteractionRequiredError: wird ausgelöst, wenn die Zustimmung erforderlich ist, muss der Benutzer MFA und etc. ausführen. Dieser Fehler kann häufig behandelt werden, indem einfach eine interaktive API initiiert wird.
  • BrowserAuthError: wird ausgelöst, wenn kein oder ungültiger Kontohinweis bereitgestellt wird, Popups blockiert und usw. Sie müssen diese errorCode entsprechend prüfen und behandeln.
    myMSALObj.ssoSilent({
        sid: sid
    }).then((response) => {
            // do something with response
        }).catch(error => {
            if (error instanceof msal.InteractionRequiredAuthError) {
                myMSALObj.loginPopup()
                    .then((response) => {
                        // do something with response
                    });
            } else if (error instanceof msal.BrowserAuthError) {
                if (error.errorCode === "silent_sso_error") {
                    // e.g. username is null
                }
                if (error.errorCode === "popup_window_error") {
                    // e.g. popups are blocked
                }
            } else {
                console.log(error);
            }
        });

Benutzerinteraktion

Wenn Sie die Kommunikation mit IdP minimieren möchten, die eine Benutzerinteraktion erfordert oder probleme mit Popups aus irgendeinem Grund auftreten, gibt es einige Optionen, die Sie berücksichtigen können:

  • Administratorzustimmung erteilen. Dadurch wird sichergestellt, dass keine Zustimmungsaufforderungen für Berechtigungen vorhanden sind, die von Ihrer App benötigt werden, wenn benutzer sich zum ersten Mal anmelden.

  • Vorabautorisieren von Client-Apps. Dadurch wird sichergestellt, dass keine Zustimmungsaufforderungen für Berechtigungen vorhanden sind, die von Ihrer Web-API benötigt werden, wenn sie von Ihren Client-Apps aufgerufen wird.

Einmaliges Abmelden

Sie können MSAL.js mit einem Front-Channel-Abmelde-URI verwenden, um Single Sign-out zwischen iframed- und übergeordneten Apps zu erzielen. Wenn Benutzer sich z. B. automatisch von iframed-Apps abmelden sollen, wenn sie sich von der übergeordneten App abmelden, sollten Sie die Front-Channel-Abmeldung für die iframed-Apps aktivieren. Dazu siehe bitte: So konfigurieren Sie eine URI für die Front-Channel-Abmeldung.