Rozpocznij pracę z MSAL React

W tym artykule dowiesz się, jak zacząć korzystać z @azure/msal-react. Omówimy inicjalizację, określanie, czy użytkownik jest uwierzytelniony, zabezpieczanie komponentów, logowanie użytkownika oraz uzyskiwanie tokenu dostępu.

Wymagania wstępne

Inicjalizacja

@azure/msal-react jest oparty na interfejsie React Context API, a wszystkie części aplikacji, które wymagają uwierzytelniania, muszą być opakowane komponentem MsalProvider. Najpierw należy zainicjować wystąpienie PublicClientApplication elementu , a następnie przekazać je MsalProvider jako prop.

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 />);

Wszystkie komponenty pod MsalProvider mają dostęp do instancji PublicClientApplication za pośrednictwem kontekstu, a także wszystkich hooków i komponentów udostępnianych przez @azure/msal-react.

Określanie, czy użytkownik jest uwierzytelniony

Większość aplikacji musi warunkowo renderować niektóre składniki na podstawie tego, czy użytkownik jest zalogowany, czy nie. @azure/msal-react Zapewnia 2 proste sposoby, aby to zrobić.

AuthenticatedTemplate i UnauthenticatedTemplate

Komponenty AuthenticatedTemplate i UnauthenticatedTemplate będą renderować swoje elementy podrzędne tylko wtedy, gdy użytkownik jest odpowiednio uwierzytelniony lub nieuwierzytelniony.

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 zaczep

Alternatywnie do opisanych powyżej komponentów opakowujących Twoja aplikacja może używać hooka useIsAuthenticated. Więcej informacji na ten temat można przeczytać w temacie Hooks in MSAL React (Haki w rozwiązaniu 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>
    );
}

Ochrona składników

Jeśli masz składniki, które chcesz pokazać tylko uwierzytelnieni użytkownikom, możesz użyć dowolnej z powyższych metod. Ale co zrobić, jeśli chcesz automatycznie wywołać logowanie, jeśli użytkownik nie jest jeszcze uwierzytelniony? @azure/msal-react oferuje 2 sposoby, aby to zrobić, za pomocą MsalAuthenticationTemplate lub hooka useMsalAuthentication.

MsalAuthenticationTemplate komponent

Składnik MsalAuthenticationTemplate wyrenderuje swoje elementy podrzędne, jeśli użytkownik jest uwierzytelniony, lub spróbuje zalogować użytkownika. Wystarczy podać typ interakcji, którego chcesz użyć (przekierowanie lub wyskakujące okienko) i opcjonalnie obiekt żądania , który ma zostać przekazany do interfejsu API logowania, składnik do wyświetlenia, gdy uwierzytelnianie jest w toku, lub składnik do wyświetlenia, jeśli wystąpi błąd.

Działający przykład tego można znaleźć w dowolnym z naszych przykładów na stronie /profile.

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 Hak

Hak useMsalAuthentication najpierw sprawdzi, czy użytkownik jest zalogowany, a następnie spróbuje zalogować użytkownika, jeśli nie ma zalogowanych użytkowników. Musisz podać typ interakcji, którego chcesz użyć (przekierowanie lub wyskakujące okienko). Spowoduje to zwrócenie wyniku operacji logowania, wszelkich błędów, które wystąpiły i funkcji logowania, której można użyć, jeśli musisz ponowić próbę.

Możesz przeczytać więcej o tym hooku w dokumentacji hooks.

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>
    );
}

Logowanie użytkownika przy użyciu interfejsów API logowania udostępnianych przez @azure/msal-browser

Innym sposobem wywołania logowania jest użycie interfejsów API @azure/msal-browser bezpośrednio z instancji PublicClientApplication dostępnej w kontekście. Istnieją 3 sposoby, aby uzyskać dostęp do instancji z kontekstu.

useMsal hak

Hak, który zwraca instancję PublicClientApplication, tablicę wszystkich aktualnie zalogowanych kont oraz wartość inProgress, która wskazuje, co msal aktualnie robi.

Więcej informacji na temat tego haka można dowiedzieć się w dokumentach o hakach.

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>
            </>
        );
    }
}

Wykorzystywanie surowego kontekstu

Jeśli używasz komponentu klasowego i nie możesz używać hooków, możesz skorzystać z surowego kontekstu MSAL za pośrednictwem MsalContext. Więcej informacji na temat używania @azure/msal-react w składnikach klasy można znaleźć tutaj.

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>
                </>
            );
        }
    }
}

Opakowywanie komponentu za pomocą komponentu wyższego rzędu withMsal

Innym sposobem użycia kontekstu MSAL zarówno w komponentach klasowych, jak i funkcyjnych, jest opakowanie komponentu za pomocą withMsal HOC, który wstrzyknie kontekst do właściwości komponentu.

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);

Uzyskiwanie tokenu dostępu

Zalecamy, aby aplikacja wywoływała interfejs API acquireTokenSilent na obiekcie PublicClientApplication za każdym razem, gdy potrzebuje tokenu dostępu, aby uzyskać dostęp do interfejsu API. Można to zrobić podobnie do sposobów opisanych w poprzedniej sekcji.

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>
    }
}

Uzyskiwanie tokenu dostępu poza składnikiem React

Jeśli potrzebujesz tokenu dostępu poza komponentem React, możesz bezpośrednio wywołać funkcję acquireTokenSilent na obiekcie PublicClientApplication. Nie zalecamy wywoływania funkcji, które zmieniają stan uwierzytelnienia użytkownika (logowanie, wylogowywanie) poza kontekstem react udostępnianym przez MsalProvider program , ponieważ składniki w kontekście mogą nie zostać prawidłowo zaktualizowane.

Pamiętaj, że użytkownik musi być zalogowany przed uzyskaniem tokenu.

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
};

Zobacz także