Erste Schritte mit MSAL React

In diesem Artikel erfahren Sie, wie Sie mit @azure/msal-react beginnen. Wir werden die Initialisierung behandeln, ermitteln, ob ein Benutzer authentifiziert ist, Komponenten schützen, einen Benutzer anmelden und ein Zugriffstoken erwerben.

Voraussetzungen

Initialisierung

@azure/msal-react basiert auf der React-Kontext-API , und alle Teile Ihrer App, die eine Authentifizierung erfordern, müssen in die MsalProvider Komponente eingeschlossen werden. Zuerst müssen Sie eine Instanz von PublicClientApplicationinitialisieren und diese dann als Prop an MsalProvider übergeben.

import React from "react";
import { createRoot } from "react-dom/client";

import { MsalProvider } from "@azure/msal-react";
import { Configuration,  PublicClientApplication } from "@azure/msal-browser";

import App from "./app.jsx";

// MSAL configuration
const configuration: Configuration = {
    auth: {
        clientId: "client-id"
    }
};

const pca = new PublicClientApplication(configuration);

// Component
const AppProvider = () => (
    <MsalProvider instance={pca}>
        <App />
    </MsalProvider>
);

const root = createRoot(document.getElementById("root"));
root.render(<AppProvider />);

Alle darunter liegenden MsalProvider Komponenten haben Zugriff auf die PublicClientApplication Instanz über den Kontext sowie alle Hooks und Komponenten, die von @azure/msal-reactihnen bereitgestellt werden.

Bestimmen, ob ein Benutzer authentifiziert ist

Die meisten Anwendungen müssen bestimmte Komponenten bedingt rendern, je nachdem, ob ein Benutzer angemeldet ist oder nicht. @azure/msal-react bietet 2 einfache Möglichkeiten, dies zu tun.

AuthenticatedTemplate und UnauthenticatedTemplate

Die AuthenticatedTemplate- und UnauthenticatedTemplate-Komponenten zeigen ihre untergeordneten Elemente nur an, je nachdem, ob ein Benutzer authentifiziert bzw. nicht authentifiziert ist.

import React from 'react';
import { AuthenticatedTemplate, UnauthenticatedTemplate } from "@azure/msal-react";

export function App() {
    return (
        <React.Fragment>
            <p>Anyone can see this paragraph.</p>
            <AuthenticatedTemplate>
                <p>At least one account is signed in!</p>
            </AuthenticatedTemplate>
            <UnauthenticatedTemplate>
                <p>No users are signed in!</p>
            </UnauthenticatedTemplate>
        </React.Fragment>
    );
}

useIsAuthenticated Haken

Als Alternative zu den oben genannten Wrapper-Komponenten, die Ihre App umgeben, kann Ihre App den Hook useIsAuthenticated verwenden. Weitere Informationen hierzu finden Sie in Hooks in MSAL React.

import React from 'react';
import { useIsAuthenticated } from "@azure/msal-react";

export function App() {
    const isAuthenticated = useIsAuthenticated();

    return (
        <React.Fragment>
            <p>Anyone can see this paragraph.</p>
            {isAuthenticated && (
                <p>At least one account is signed in!</p>
            )}
            {!isAuthenticated && (
                <p>No users are signed in!</p>
            )}
        </React.Fragment>
    );
}

Schützen von Komponenten

Wenn Sie über Komponenten verfügen, die nur authentifizierten Benutzern angezeigt werden sollen, können Sie eine der oben genannten Methoden verwenden. Aber was geschieht, wenn Sie automatisch eine Anmeldung aufrufen möchten, wenn ein Benutzer noch nicht authentifiziert ist? @azure/msal-react bietet 2 Möglichkeiten, dies mit dem MsalAuthenticationTemplate oder dem useMsalAuthentication Hook zu tun.

MsalAuthenticationTemplate Komponente

Die MsalAuthenticationTemplate Komponente rendert die untergeordneten Elemente, wenn ein Benutzer authentifiziert ist oder versucht, einen Benutzer anzumelden. Geben Sie es einfach mit dem Interaktionstyp an, den Sie verwenden möchten (Umleitung oder Popup) und optional ein Anforderungsobjekt , das an die Anmelde-API übergeben werden soll, eine Komponente, die angezeigt wird, während die Authentifizierung ausgeführt wird, oder eine Komponente, die angezeigt wird, wenn ein Fehler auftritt.

Ein funktionierendes Beispiel hierfür finden Sie in einem unserer Beispiele auf der /profile Seite.

import React from "react";
import { MsalAuthenticationTemplate } from "@azure/msal-react";
import { InteractionType } from "@azure/msal-browser";

function ErrorComponent({error}) {
    return <p>An Error Occurred: {error}</p>;
}

function LoadingComponent() {
    return <p>Authentication in progress...</p>;
}

export function Example() {
    const authRequest = {
        scopes: ["openid", "profile"]
    };

    return (
        // authenticationRequest, errorComponent and loadingComponent props are optional
        <MsalAuthenticationTemplate 
            interactionType={InteractionType.Popup} 
            authenticationRequest={authRequest} 
            errorComponent={ErrorComponent} 
            loadingComponent={LoadingComponent}
        >
            <p>At least one account is signed in!</p>
        </MsalAuthenticationTemplate>
      )
};

useMsalAuthentication Haken

Der useMsalAuthentication Hook überprüft zuerst, ob ein Benutzer angemeldet ist, und versucht dann, einen Benutzer anzumelden, wenn keine Benutzer angemeldet sind. Sie müssen den Interaktionstyp angeben, den Sie verwenden möchten (Umleitung oder Popup). Es gibt das Ergebnis des Anmeldevorgangs, alle aufgetretenen Fehler und die Anmeldefunktion zurück, die Sie verwenden können, wenn Sie den Vorgang wiederholen müssen.

Weitere Informationen zu diesem Hook finden Sie im Hooks-Dokument.

import React from 'react';
import { useMsalAuthentication } from "@azure/msal-react";
import { InteractionType } from '@azure/msal-browser';

export function App() {
    const {login, result, error} = useMsalAuthentication(InteractionType.Popup);

    return (
        <React.Fragment>
            <p>Anyone can see this paragraph.</p>
            <AuthenticatedTemplate>
                <p>At least one account is signed in!</p>
            </AuthenticatedTemplate>
            <UnauthenticatedTemplate>
                <p>No users are signed in!</p>
            </UnauthenticatedTemplate>
        </React.Fragment>
    );
}

Melden Sie einen Benutzer mit den von @azure/msal-browser bereitgestellten Login-APIs an

Eine weitere Möglichkeit, eine Anmeldung auszulösen, besteht darin, @azure/msal-browser APIs direkt von der PublicClientApplication-Instanz im Kontext zu verwenden. Es gibt drei Möglichkeiten, über den Kontext auf die Instanz zuzugreifen.

useMsal Haken

Ein Hook, der die PublicClientApplication Instanz zurückgibt, ein Array aller derzeit angemeldeten Konten und ein inProgress Wert, der Ihnen angibt, was msal derzeit ausführt.

Weitere Informationen zu diesem Hook finden Sie im Hooks-Dokument.

import React from 'react';
import { useMsal } from "@azure/msal-react";

export function App() {
    const { instance, accounts, inProgress } = useMsal();

    if (accounts.length > 0) {
        return <span>There are currently {accounts.length} users signed in!</span>
    } else if (inProgress === "login") {
        return <span>Login is currently in progress!</span>
    } else {
        return (
            <>
                <span>There are currently no users signed in!</span>
                <button onClick={() => instance.loginPopup()}>Login</button>
            </>
        );
    }
}

Verwenden des rohen Kontexts

Wenn Sie eine Klassenkomponente verwenden und keine Hooks nutzen können, können Sie über MsalContext auf den rohen msal-Kontext zugreifen. Weitere Informationen zur Verwendung @azure/msal-react in Klassenkomponenten finden Sie hier.

import React from "react";
import { MsalContext } from "@azure/msal-react";

class App extends React.Component {
    static contextType = MsalContext;

    render() {
        if (this.context.accounts.length > 0) {
            return <span>There are currently {this.context.accounts.length} users signed in!</span>
        } else if (this.context.inProgress === "login") {
            return <span>Login is currently in progress!</span>
        } else {
            return (
                <>
                    <span>There are currently no users signed in!</span>
                    <button onClick={() => this.context.instance.loginPopup()}>Login</button>
                </>
            );
        }
    }
}

Ihre Komponente mit der withMsal Higher-Order-Component umschließen

Eine weitere Möglichkeit, den MSAL-Kontext sowohl in Klassen- als auch in Funktionskomponenten zu verwenden, besteht darin, Ihre Komponente mit dem HOC withMsal zu umschließen, das den Kontext in die Props Ihrer Komponente einfügt.

import React from "react";
import { withMsal } from "@azure/msal-react";

class LoginButton extends React.Component {
    render() {
        const isAuthenticated = this.props.msalContext.accounts.length > 0;
        const msalInstance = this.props.msalContext.instance;
        if (isAuthenticated) {
            return <button onClick={() => msalInstance.logout()}>Logout</button>    
        } else {
            return <button onClick={() => msalInstance.loginPopup()}>Login</button>
        }
    }
}

export default YourWrappedComponent = withMsal(LoginButton);

Abrufen eines Zugriffstokens

Es wird empfohlen, dass Ihre App die acquireTokenSilent API für Ihr PublicClientApplication Objekt jedes Mal aufruft, wenn Sie ein Zugriffstoken für den Zugriff auf eine API benötigen. Dies kann ähnlich wie im vorherigen Abschnitt beschrieben werden.

import React, { useState, useEffect } from "react"
import { useMsal, useAccount } from "@azure/msal-react";

export function App() {
    const { instance, accounts, inProgress } = useMsal();
    const account = useAccount(accounts[0] || {});
    const [apiData, setApiData] = useState(null);

    useEffect(() => {
        if (account) {
            instance.acquireTokenSilent({
                scopes: ["User.Read"],
                account: account
            }).then((response) => {
                if(response) {
                    callMsGraph(response.accessToken).then((result) => setApiData(result));
                }
            });
        }
    }, [account, instance]);

    if (accounts.length > 0) {
        return (
            <>
                <span>There are currently {accounts.length} users signed in!</span>
                {apiData && (<span>Data retreived from API: {JSON.stringify(apiData)}</span>)}
            </>
        );
    } else if (inProgress === "login") {
        return <span>Login is currently in progress!</span>
    } else {
        return <span>There are currently no users signed in!</span>
    }
}

Abrufen eines Zugriffstokens außerhalb einer React-Komponente

Wenn Sie außerhalb einer React-Komponente ein Zugriffstoken benötigen, können Sie die Funktion acquireTokenSilent direkt auf dem PublicClientApplication aufrufen. Wir empfehlen nicht, Funktionen aufzurufen, die den Authentifizierungsstatus des Benutzers ändern (Anmeldung, Abmeldung), außerhalb des von MsalProvider bereitgestellten React-Kontexts, da die Komponenten innerhalb des Kontexts andernfalls möglicherweise nicht ordnungsgemäß aktualisiert werden.

Denken Sie daran, dass der Benutzer angemeldet sein muss, bevor Sie ein Token abrufen können.

import { PublicClientApplication } from "@azure/msal-browser";

// This should be the same instance you pass to MsalProvider
const msalInstance = new PublicClientApplication(config);

const acquireAccessToken = async (msalInstance) => {
    const activeAccount = msalInstance.getActiveAccount(); // This will only return a non-null value if you have logic somewhere else that calls the setActiveAccount API
    const accounts = msalInstance.getAllAccounts();

    if (!activeAccount && accounts.length === 0) {
        /*
        * User is not signed in. Throw error or wait for user to login.
        * Do not attempt to log a user in outside of the context of MsalProvider
        */   
    }
    const request = {
        scopes: ["User.Read"],
        account: activeAccount || accounts[0]
    };

    const authResult = await msalInstance.acquireTokenSilent(request);

    return authResult.accessToken
};

Siehe auch