Anmelden von Benutzern

Bevor Sie hier beginnen, stellen Sie sicher, dass Sie wissen, wie Sie das Anwendungsobjekt initialisieren.

Die Anmelde-APIs in MSAL rufen ein authorization code ab, das für einen angemeldeten Benutzer gegen ein ID-Token ausgetauscht werden kann, wobei gleichzeitig Berechtigungsbereiche für eine zusätzliche Ressource genehmigt werden, sowie ein Zugriffstoken, das die vom Benutzer genehmigten Berechtigungsbereiche enthält, damit Ihre App die API sicher aufrufen kann.

Auswählen eines Interaktionstyps

Lesen Sie hier nach, wenn Sie sich bezüglich der Unterschiede zwischen loginRedirect und loginPopup nicht sicher sind.

Anmelden des Benutzers

Sie müssen ein Anforderungsobjekt an die Anmelde-APIs übergeben. Mit diesem Objekt können Sie unterschiedliche Parameter in der Anforderung verwenden. Weitere Informationen zu den Anforderungsobjektparametern finden Sie hier .

Bei Anmeldeanforderungen sind alle Parameter optional, sodass Sie einfach ein leeres Objekt senden können.

  • Popup
try {
    const loginResponse = await msalInstance.loginPopup({});
} catch (err) {
    // handle error
}
  • Umleitung
try {
    msalInstance.loginRedirect({});
} catch (err) {
    // handle error
}

Oder Sie können eine Reihe von Scopes senden, denen vorab zugestimmt werden soll:

  • Popup
var loginRequest = {
    scopes: ["user.read", "mail.send"] // optional Array<string>
};

try {
    const loginResponse = await msalInstance.loginPopup(loginRequest);
} catch (err) {
    // handle error
}
  • Umleitung
var loginRequest = {
    scopes: ["user.read", "mail.send"] // optional Array<string>
};

try {
    msalInstance.loginRedirect(loginRequest);
} catch (err) {
    // handle error
}

Konto-APIs

Wenn ein Anmeldeaufruf erfolgreich war, können Sie die getAllAccounts() Funktion verwenden, um Informationen zu aktuell angemeldeten Benutzern abzurufen.

const myAccounts: AccountInfo[] = msalInstance.getAllAccounts();

Wenn Sie die Kontoinformationen kennen, können Sie die Kontoinformationen auch mithilfe der getAccount() API abrufen:

const username = "test@contoso.com";
const myAccount: AccountInfo = msalInstance.getAccount({ username });

const homeAccountId = "userid.hometenantid"; // Best to retrieve the homeAccountId from an account object previously obtained through msal
const myAccount: AccountInfo = msalInstance.getAccount({ homeAccountId });

Note

username Die Filterung erfolgt aus Gründen der Einfachheit und sollte als weniger zuverlässig betrachtet werden als die Suche basierend auf homeAccountId. Verwenden Sie nach Möglichkeit homeAccountId.

In B2C-Szenarien muss Ihr B2C-Mandant so konfiguriert sein, dass der Anspruch emails für idTokens zurückgegeben wird, um den Filter username in der getAccount()-API zu verwenden.

Diese APIs geben ein Kontoobjekt oder ein Array von Kontoobjekten mit der folgenden Signatur zurück:

{
    // home account identifier for this account object
    homeAccountId: string;
    // Entity who issued the token represented as a full host of it (e.g. login.microsoftonline.com)
    environment: string;
    // Full tenant or organizational id that this account belongs to
    tenantId: string;
    // preferred_username claim of the id_token that represents this account.
    username: string;
};

Stille Anmeldung mit ssoSilent()

Wenn Sie bereits über eine Sitzung verfügen, die mit dem Authentifizierungsserver vorhanden ist, können Sie die ssoSilent()-API verwenden, um Anforderungen für Token ohne Interaktion zu stellen.

Mit Benutzertipp

Wenn Sie bereits über die Anmeldeinformationen des Benutzers verfügen, können Sie dies an die API übergeben, um die Leistung zu verbessern und sicherzustellen, dass der Autorisierungsserver nach der richtigen Kontositzung sucht. Sie können dem Anforderungsobjekt eines der folgenden Elemente übergeben, um erfolgreich ein Token ohne Benutzerinteraktion abzurufen.

Es wird empfohlen, den login_hint optionalen ID-Token-Anspruch zu verwenden (der ssoSilent als loginHint bereitgestellt wird), da er der zuverlässigste Kontohinweis für stille (und interaktive) Anforderungen ist.

  • account (die mithilfe einer der Konto-APIs abgerufen werden können)
  • sid (die aus dem idTokenClaims eines account-Objekts abgerufen werden kann)
  • login_hint (kann wie folgt abgerufen werden)
    • Als loginHint-Eigenschaft des Kontoobjekts (empfohlen)
    • Als login_hint ID-Token-Claim des Kontoobjekts (empfohlen)
    • Als username-Eigenschaft des Kontoobjekts (nicht empfohlen)
    • Als ID-Tokenanspruch des Kontoobjekts upn (nicht empfohlen)

Note

Die Eigenschaften username und upn werden teilweise anstelle des eigentlichen login_hint-Anspruchs unterstützt, werden jedoch nicht empfohlen. Verwenden Sie die Kontoeigenschaften von loginHint oder idTokenClaims.login_hint, sofern sie verfügbar sind.

Beim Übergeben eines Kontos wird zuerst nach dem optionalen login_hint ID-Token-Claim (bevorzugt) gesucht, dann nach dem optionalen sid ID-Token-Claim, und anschließend wird auf loginHint (falls vorhanden) oder den Kontobenutzernamen zurückgegriffen.

const account = msalInstance.getAllAccounts()[0];

const silentRequest = {
    scopes: ["User.Read", "Mail.Read"],
    loginHint: account.loginHint, // alternatively, account.idTokenClaims.login_hint
};

try {
    const loginResponse = await msalInstance.ssoSilent(silentRequest);
} catch (err) {
    if (err instanceof InteractionRequiredAuthError) {
        const loginResponse = await msalInstance.loginPopup(silentRequest).catch(error => {
            // handle error
        });
    } else {
        // handle error
    }
}

Ohne Benutzerhinweis

Wenn nicht genügend Informationen über den Benutzer verfügbar sind, können Sie versuchen, die ssoSilent API zu verwenden, ohne ein account, sid oder login_hint zu übergeben.

const silentRequest = {
    scopes: ["User.Read", "Mail.Read"]
};

Beachten Sie jedoch, dass die Wahrscheinlichkeit stiller Fehler bei der Anmeldung höher ist, wenn Ihre Anwendung Codepfade für mehrere Benutzer innerhalb einer einzigen Browsersitzung enthält oder wenn der Benutzer innerhalb derselben Browsersitzung über mehrere Konten verfügt. Möglicherweise wird der folgende Fehler angezeigt, falls vom Autorisierungsserver mehrere Kontositzungen gefunden wurden:

InteractionRequiredAuthError: interaction_required: AADSTS16000: Either multiple user identities are available for the current request or selected account is not supported for the scenario.

Dies gibt an, dass der Server nicht bestimmen konnte, welches Konto angemeldet werden soll, und erfordert entweder einen der oben genannten Parameter (account, , login_hint, sid) oder eine interaktive Anmeldung, um das Konto auszuwählen.

Warning

Bei Verwendung ssoSilentversucht der Dienst, die Umleitungs-URI-Seite in einem unsichtbaren eingebetteten iframe zu laden. Content-Security-Richtlinien und HTTP-Headerwerte, die in der Seitenantwort der Umleitungs-URI Ihrer App vorhanden sind, wie X-FRAME-OPTIONS: DENY und X-FRAME-OPTIONS: SAMEORIGIN, können verhindern, dass Ihre App im IFrame geladen wird, und dadurch stilles SSO effektiv blockieren. Wenn Sie ssoSilent verwenden möchten, stellen Sie sicher, dass die Weiterleitungs-URI auf eine Seite verweist, die keine solchen Richtlinien implementiert.

Überlegungen zur Redirect-URI

Für alle Authentifizierungsflüsse ist jetzt eine dedizierte Umleitungsseite erforderlich, die die MSAL-Umleitungsbrücke implementiert. Dies ist erforderlich, um COOP-Header (Cross-Origin-Opener-Policy) zu unterstützen und die sichere Kommunikation zwischen Popup-/iframe-Fenstern und der Hauptanwendung zu ermöglichen.

Einrichten der Umleitungsseite

Ihre redirectUri muss auf eine dedizierte Seite verweisen, die das Redirect-Bridge-Skript lädt. Diese Seite sollte:

  1. Laden des Umleitungsbrückenskripts – Dieses Skript behandelt die Kommunikation mit dem Hauptfenster.
  2. Kein JavaScript mit Ausnahme des Brückenskripts enthalten – Die Umleitungsseite sollte nur das Brückenskript ausführen.
  3. Keine Routinglogik enthalten – Vermeiden von Routerbibliotheken, die die Hashverarbeitung beeinträchtigen könnten
  4. In Ihrer App-Registrierung registriert werden – Der URI muss genau mit dem übereinstimmen, was im Azure-Portal registriert ist.

Beispiel für eine Umleitungsseite (bei Verwendung eines Bundlers wie Vite oder Webpack):

<!DOCTYPE html>
<html>
<head>
    <title>Redirect</title>
</head>
<body>
    <p>Processing authentication...</p>
    <script type="module">
        import { broadcastResponseToMainFrame } from "@azure/msal-browser/redirect-bridge";

        broadcastResponseToMainFrame();
    </script>
</body>
</html>

Note

Der @azure/msal-browser/redirect-bridge Bezeichner muss durch einen Bundler (Vite, Webpack usw.) aufgelöst werden – es handelt sich nicht um eine URL, die Browser direkt abrufen können. Frameworkspezifische Anweisungen finden Sie im Setuphandbuch für Umleitungsbrücken.

Configuration

Sie können die redirectUri global in Ihrer MSAL-Konfiguration oder auf Anforderungsbasis festlegen:

Globale Konfiguration:

const msalConfig = {
    auth: {
        clientId: "your-client-id",
        authority: "https://login.microsoftonline.com/common",
        redirectUri: "http://localhost:3000/redirect"
    }
};

const msalInstance = new PublicClientApplication(msalConfig);

Konfiguration pro Anforderung:

msalInstance.loginPopup({
    scopes: ["user.read"],
    redirectUri: "http://localhost:3000/redirect"
});

Weitere Informationen und vollständige Beispielimplementierungen finden Sie unter:

Umgang mit Popup-Fehlern interaction_in_progress

Für Popupflüsse können Sie die overrideInteractionInProgress Kennzeichnung verwenden, um eine ausstehende Interaktion abzubrechen und eine neue zu starten. Dies ist nützlich für Wiederherstellungsszenarien, in denen der Benutzer ein Popup abgebrochen hat oder eine Interaktion fehlgeschlagen ist.

Note

Dieses Feature ist nur für Popupflüsse verfügbar und wird für Umleitungsflüsse nicht unterstützt. Mit dem COOP-Header (Cross-Origin-Opener-Policy) wird die herkömmliche window.opener-Verbindung getrennt, sodass Popup-Fenster nur noch über BroadcastChannel mit dem Hauptfenster kommunizieren können.

Important

Wenn dies auf true gesetzt wird, werden alle ausstehenden Popup-Authentifizierungsanfragen zwangsweise abgebrochen, es werden jedoch keine geöffneten Pop-ups geschlossen.

Bei Festlegung auf true:

  • Wenn derzeit eine andere Popupinteraktion ausgeführt wird, wird sie erzwungen abgebrochen, aber alle geöffneten Popups werden nicht geschlossen.
  • Die ausstehende Interaktion wird mit dem Fehler interaction_in_progress_cancelled zurückgewiesen.
  • Der neue Popup-Ablauf wird sofort ausgeführt.

Gültige Anwendungsfälle:

  • Wiederherstellen von Fehlern, bei denen der Benutzer ein Popup abgebrochen hat (Popup wurde geschlossen, ohne die Authentifizierung abzuschließen)
  • Implementieren von benutzerdefinierten Fehlerwiederherstellungsflüssen
  • Bereitstellen eines "Wiederholungsmechanismus" nach einer fehlgeschlagenen Popupinteraktion

Vorgabe:false

Wichtig: Nur beim Klick auf eine Schaltfläche verwenden

Versuchen Sie nicht automatisch erneut , wenn sie einen interaction_in_progress Fehler abfangen. Die Außerkraftsetzung sollte nur durch eine explizite Benutzeraktion ausgelöst werden (z. B. durch Klicken auf eine Schaltfläche "Wiederholen"). Das automatische Überschreiben von Interaktionen kann dazu führen:

  • Rennbedingungen zwischen mehreren Authentifizierungsflüssen
  • Unerwartete Abbrüche legitimer Authentifizierungsversuche
  • Schlechte Benutzererfahrung beim Starten und Unerwartetes Beenden von Authentifizierungsflüssen
  • Viele offene Pop-ups, die nicht zu einer erfolgreichen Authentifizierungsantwort führen

Beispiel: Ordnungsgemäße Fehlerbehandlung bei vom Benutzer ausgelöster Wiederholung

Vollständige Implementierungen mit visuellem Feedback finden Sie unter:

  • Express-Beispiel – Veranschaulicht die JavaScript-Implementierung mit benutzerdefiniertem CSS
  • React Router-Beispiel – Veranschaulicht die React-Implementierung mit Material-UI-Komponenten

Beide Beispiele veranschaulichen:

  • Warnmeldung, die während der Popupauthentifizierung angezeigt wird
  • Modales Dialogfeld wiederholen mit klarer Erklärung, wenn interaction_in_progress ein Fehler auftritt
  • Ordnungsgemäße Zustandsverwaltung für vom Benutzer ausgelöste Wiederholungsversuche
  • Produktionsfähige UI-Komponenten
// State to track if user wants to retry
let userWantsRetry = false;

// Button click handler
async function handleLoginClick() {
    try {
        const loginRequest = {
            scopes: ["user.read"]
        };

        // If user explicitly clicked retry, override the existing interaction
        if (userWantsRetry) {
            loginRequest.overrideInteractionInProgress = true;
            userWantsRetry = false; // Reset flag
        }

        const response = await msalInstance.loginPopup(loginRequest);
        // Handle successful login
    } catch (error) {
        if (error.errorCode === 'interaction_in_progress') {
            // Show retry button to user - DO NOT automatically retry
            showRetryButton();
        } else {
            // Handle other errors
            console.error(error);
        }
    }
}

// Retry button click handler
function handleRetryClick() {
    userWantsRetry = true; // Set flag for next login attempt
    handleLoginClick(); // User explicitly requested retry
}

Beispiel: React-Komponente mit vom Benutzer ausgelöster Wiederholung

function LoginButton() {
    const { instance } = useMsal();
    const [showRetry, setShowRetry] = useState(false);
    const [retryRequested, setRetryRequested] = useState(false);

    const handleLogin = async () => {
        try {
            const loginRequest = {
                scopes: ["user.read"],
                // Only override if user clicked the retry button
                overrideInteractionInProgress: retryRequested
            };

            setRetryRequested(false); // Reset retry flag

            const response = await instance.loginPopup(loginRequest);
            setShowRetry(false);
        } catch (error) {
            if (error.errorCode === 'interaction_in_progress') {
                // Show retry button - let user decide whether to retry
                setShowRetry(true);
            } else {
                console.error(error);
            }
        }
    };

    const handleRetry = () => {
        setRetryRequested(true); // User explicitly requested retry
        handleLogin();
    };

    return (
        <div>
            <button onClick={handleLogin}>Login</button>
            {showRetry && (
                <button onClick={handleRetry}>
                    Retry Login (Cancel Pending)
                </button>
            )}
        </div>
    );
}

Nächste Schritte

Erfahren Sie, wie Sie ein Zugriffstoken erwerben und verwenden können!