Przewodnik migracji z MSAL v1 do @azure/msal-react i @azure/msal-browser

Ten artykuł zawiera omówienie migracji z MSAL v1 do @azure/msal-react i @azure/msal-browser. Zalecamy migrację w celu zwiększenia wydajności i lepszego zabezpieczeń przy użyciu przepływu kodu autoryzacji przy użyciu protokołu PKCE i dostępu warunkowego. Ponadto istnieje lepsza obsługa aplikacji jednostronicowych.

Wymagania wstępne

  • Konto platformy Azure z aktywną subskrypcją. Bezpłatne tworzenie konta
  • Istniejąca aplikacja zarejestrowana w Twojej dzierżawie Microsoft Entra.

Aktualizowanie rejestracji aplikacji

Biblioteka @azure/msal-react jest nakładką na @azure/msal-browser, która implementuje przepływ kodu autoryzacyjnego z PKCE. To znacząca zmiana w stosunku do biblioteki MSAL v1, która implementuje przepływ niejawny.

Musisz utworzyć nową rejestrację aplikacji lub zaktualizować istniejącą, aby użyć nowego redirectUri typu "SPA". Aby uzyskać więcej informacji , zobacz Aplikacja jednostronicowa: Rejestracja aplikacji .

Instalacja @azure/msal-react i @azure/msal-browser

Zarówno @azure/msal-react, jak i jego zależność typu peer @azure/msal-browser można zainstalować z npm. Ważne jest odinstalowanie starego pakietu MSAL. Otwórz terminal i uruchom następujące polecenia.

npm uninstall msal
npm install @azure/msal-react @azure/msal-browser

Aktualizacja z react-aad-msal

Jeśli Twoja aplikacja obecnie używa React Microsoft Entra MSAL do uwierzytelniania i chcesz przeprowadzić migrację do @azure/msal-react, w tej sekcji omówiono różnice między obiema bibliotekami oraz niektóre zmiany, które należy wprowadzić. React Microsoft Entra MSAL jest biblioteką zewnętrzną, a ponieważ biblioteka MSAL React została zbudowana od podstaw, mogą występować przypadki brzegowe, które nie są uwzględnione lub obsługiwane przez bibliotekę MSAL React.

Poniżej przedstawiono funkcje obsługiwane w react-aad-msal, które nie są obsługiwane w @azure/msal-react:

  • Weryfikowanie wygaśnięcia identyfikatora IdToken przed renderowaniem składników chronionych i automatycznego odświeżania wygasłych identyfikatorów IdTokens
  • Wbudowana obsługa store Redux (alternatywa poniżej)

W innych przypadkach możliwych przy użyciu react-aad-msal, ale już niemożliwych przy użyciu @azure/msal-react, utwórz zgłoszenie w repozytorium GitHub microsoft-authentication-library-for-js.

Inicjalizacja

W react-aad-msal inicjalizujesz instancję biblioteki MSAL, tworząc obiekt MsalAuthProvider, który jest następnie przekazywany do składnika AzureAD.

import { MsalAuthProvider } from "react-aad-msal";

const authProvider = new MsalAuthProvider(config, authenticationParameters, options);

W @azure/msal-react inicjujesz instancję MSAL za pomocą elementu PublicClientApplication eksportowanego z @azure/msal-browser, która jest następnie przekazywana do komponentu MsalProvider eksportowanego z @azure/msal-react. Opcje konfiguracji są w dużej mierze podobne między msal i @azure/msal-browser, jednak można odwołać się do typu konfiguracji dla najbardziej aktualnych opcji konfiguracji.

Parametry authenticationParameters i options używane w react-aad-msal nie są używane w @azure/msal-react, chociaż podobną funkcjonalność można uzyskać w poszczególnych komponentach. Zostanie to wyjaśnione w dalszej części tego dokumentu.

@azure/msal-react używa React Context API do udostępniania PublicClientApplication oraz stanu uwierzytelniania w całym drzewie komponentów.

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

const pca = new PublicClientApplication(config);

function App() {
    return (
        <MsalProvider instance={pca}>
            <YourAppComponents />
        </MsalProvider>
    );
}

Ogólne uwagi dotyczące MsalProvider składnika:

  • Wszystkie komponenty, które potrzebują dostępu do stanu uwierzytelniania albo do hooków/komponentów udostępnianych przez @azure/msal-react, muszą mieć w wyższej części drzewa komponentów element MsalProvider, dlatego zaleca się renderowanie MsalProvider możliwie jak najbliżej korzenia.
  • Aplikacja nie powinna renderować więcej niż 1 MsalProvider składnika na żadnej stronie.
  • Nie zalecamy inicjowania PublicClientApplication wewnątrz komponentu ze względu na możliwość ponownego renderowania

Ochrona składników

Komponenty w react-aad-msal są chronione za pomocą komponentu AzureAD lub HOC withAuthentication, który wewnętrznie opakowuje komponent za pomocą AzureAD. Składnik AzureAD będzie renderować składniki podrzędne tylko wtedy, gdy użytkownik jest uwierzytelniony i opcjonalnie inicjuje logowanie, jeśli żaden użytkownik nie jest uwierzytelniony. Opcje używane podczas logowania (np. Scopes, to, czy użyć wyskakującego okna czy przekierowania itp.) są określane wcześniej, podczas tworzenia właściwości authProvider.

import { MsalAuthProvider } from "react-aad-msal";

const authProvider = new MsalAuthProvider(config, authenticationParameters, options);

function App() {
    return (
        <AzureAD provider={authProvider} forceLogin={true}>
            <span>Only authenticated users can see me.</span>
        </AzureAD>
    );
}

@azure/msal-react, z drugiej strony, daje deweloperom większą kontrolę nad tym, co i komu chcą wyświetlać.

  • Składnik AuthenticatedTemplate renderuje elementy podrzędne w przypadku uwierzytelnienia użytkownika
  • Składnik UnauthenticatedTemplate będzie renderować elementy podrzędne, jeśli użytkownik nie jest uwierzytelniony
  • Składnik MsalAuthenticationTemplate automatycznie zainicjuje logowanie, jeśli użytkownik jest nieuwierzytelniony, a następnie renderuje elementy podrzędne po uwierzytelnieniu użytkownika.
import { PublicClientApplication, InteractionType } from "@azure/msal-browser";
import { MsalProvider, AuthenticatedTemplate, UnauthenticatedTemplate, MsalAuthenticationTemplate } from "@azure/msal-react";

const pca = new PublicClientApplication(config);

function App() {
    return (
        <MsalProvider instance={pca}>
            <AuthenticatedTemplate>
                <span>Only authenticated users can see me.</span>
            </AuthenticatedTemplate>
            <UnauthenticatedTemplate>
                <span>Only unauthenticated users can see me.</span>
            </UnauthenticatedTemplate>
            <MsalAuthenticationTemplate interactionType={InteractionType.Popup} authenticationRequest={request}>
                <span>Only authenticated users can see me. Unauthenticated users will get a popup asking them to login first.</span>
            </MsalAuthenticationTemplate>
        </MsalProvider>
    );
}

Ponadto, jeśli wolisz skorzystać z podejścia opartego na hookach, @azure/msal-react udostępnia kilka hooków, których możesz użyć do osiągnięcia podobnych rezultatów. To tylko kilka podstawowych przykładów, a więcej informacji znajdziesz w hookach React biblioteki MSAL.

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

const pca = new PublicClientApplication(config);

function App() {
    return (
        <MsalProvider instance={pca}>
            <ExampleComponent />
        </MsalProvider>
    );
}

function ExampleComponent() {
    const isAuthenticated = useIsAuthenticated();
    const { error } = useMsalAuthentication(InteractionType.Popup, request); // Will initiate a popup login if user is unauthenticated

    if (isAuthenticated) {
        return <span>Only authenticated users can see me.</span>
    } else if (error) {
        return <span>An error occurred during login!</span>
    } else {
        return <span>Only unauthenticated users can see me.</span>
    }
}

Uzyskiwanie tokenu dostępu

react-aad-msal uwidacznia metodę getAccessToken , której można użyć do uzyskania tokenu dostępu przed wywołaniem interfejsu API.

import { MsalAuthProvider } from "react-aad-msal";

const authProvider = new MsalAuthProvider(config, authenticationParameters, options);
const accessToken = authProvider.getAccessToken();

Korzystając z @azure/msal-react i @azure/msal-browser, wywołasz acquireTokenSilent na instancji PublicClientApplication.

Jeśli chcesz uzyskać token dostępu wewnątrz komponentu lub hooka znajdującego się w obrębie MsalProvider, możesz użyć hooka useMsal, aby uzyskać potrzebne obiekty.

import { useState } from "react";
import { useMsal } from "@azure/msal-react";
import { InteractionRequiredAuthError } from "@azure/msal-browser";

function useAccessToken() {
    const { instance, accounts } = useMsal();
    const [accessToken, setAccessToken] = useState(null);

    if (accounts.length > 0) {
        const request = {
            scopes: ["User.Read"],
            account: accounts[0]
        };
        instance.acquireTokenSilent(request).then(response => {
            setAccessToken(response.accessToken);
        }).catch(error => {
            // acquireTokenSilent can fail for a number of reasons, fallback to interaction
            if (error instanceof InteractionRequiredAuthError) {
                instance.acquireTokenPopup(request).then(response => {
                    setAccessToken(response.accessToken);
                });
            }
        });
    }

    return accessToken;
}

Jeśli musisz uzyskać token dostępu poza kontekstem MsalProvider, możesz bezpośrednio użyć wystąpienia PublicClientApplication i wywołać metodę getAllAccounts(), aby uzyskać obiekt konta.

Ważna

Podejmuj próbę dyskretnego uzyskania tokenu tylko poza kontekstem MsalProvider. Nie należy wywoływać metody interaktywnej (przekierowania lub wyskakującego okienka) poza kontekstem MsalProvider.

Poniższy przykład pokazuje inicjalizację PublicClientApplication w celach demonstracyjnych. PublicClientApplication należy inicjalizować tylko raz przy każdym załadowaniu strony i należy tu użyć tej samej instancji, którą przekazujesz do MsalProvider.

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

const pca = new PublicClientApplication(config);
const accounts = pca.getAllAccounts();

async function getAccessToken() {
    if (accounts.length > 0) {
        const request = {
            scopes: ["User.Read"],
            account: accounts[0]
        }
        const accessToken = await pca.acquireTokenSilent(request).then((response) => {
            return response.accessToken;
        }).catch(error => {
            // Do not fallback to interaction when running outside the context of MsalProvider. Interaction should always be done inside context.
            console.log(error);
            return null;
        });

        return accessToken;
    }

    return null;
}

Uzyskiwanie tokenu identyfikatora

react-aad-msal udostępnił getIdToken funkcję do pobierania lub odnawiania tokenu idToken.

import { MsalAuthProvider } from "react-aad-msal";

const authProvider = new MsalAuthProvider(config, authenticationParameters, options);
const token = await authProvider.getIdToken();
const idToken = token.idToken.rawIdToken;

Możesz również zapoznać się ze wzorcem żądania clientId jako jedynego zakresu w celu odzyskania identyfikatora idToken. Nie jest to już obsługiwany wzorzec w pliku @azure/msal-browser.

W @azure/msal-react i @azure/msal-browser wszystkie wywołania dotyczące tokenów będą zwracać zarówno token dostępu, jak i token ID, a wszystkie odnowienia tokenu dostępu będą również odnawiać token ID.

Jeśli chcesz uzyskać token ID wewnątrz komponentu lub hooka znajdującego się pod MsalProvider, możesz użyć hooka useMsal, aby pobrać potrzebne obiekty.

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

function useIdToken() {
    const { instance, accounts } = useMsal();
    const [idToken, setIdToken] = useState(null);

    if (accounts.length > 0) {
        const request = {
            scopes: ["openid"],
            account: accounts[0]
        };
        instance.acquireTokenSilent(request).then(response => {
            setIdToken(response.idToken);
        }).catch(error => {
            // acquireTokenSilent can fail for a number of reasons, fallback to interaction
            if (error instanceof InteractionRequiredAuthError) {
                instance.acquireTokenPopup(request).then(response => {
                    setIdToken(response.idToken);
                });
            }
        });
    }

    return idToken;
}

Jeśli musisz uzyskać token ID poza kontekstem MsalProvider, możesz bezpośrednio użyć instancji PublicClientApplication i wywołać metodę getAllAccounts(), aby uzyskać obiekt konta.

Ważna

Podejmuj próbę dyskretnego uzyskania tokenu tylko poza kontekstem MsalProvider. Nie należy wywoływać metody interaktywnej (przekierowania lub wyskakującego okienka) poza kontekstem MsalProvider.

Poniższy przykład pokazuje inicjalizację PublicClientApplication do celów demonstracyjnych. PublicClientApplication powinno być inicjowane tylko raz przy każdym załadowaniu strony i należy użyć tutaj tej samej instancji, którą przekazujesz do MsalProvider.

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

const pca = new PublicClientApplication(config);
const accounts = pca.getAllAccounts();

async function getIdToken() {
    if (accounts.length > 0) {
        const request = {
            scopes: ["openid"],
            account: accounts[0]
        }
        const idToken = await pca.acquireTokenSilent(request).then((response) => {
            return response.idToken;
        }).catch (error => {
            // Do not fallback to interaction when running outside the context of MsalProvider. Interaction should always be done inside context.
            console.log(error);
            return null;
        });

        return idToken
    }

    return null;
}

Aktualizowanie integracji ze store’em Redux / reagowanie na zdarzenia

react-aad-msal zapewniał gotową integrację ze storem Redux, wysyłając akcje, gdy występowały zdarzenia, takie jak logowanie lub wylogowanie. @azure/msal-react nie udostępnia tej funkcjonalności, jednak podobną funkcjonalność można uzyskać przy użyciu interfejsu API zdarzeń udostępnianego przez @azure/msal-browser.

Można zarejestrować funkcję zwrotną zdarzenia, która będzie wywoływana za każdym razem, gdy zdarzenie zostanie rozgłoszone (np. LOGIN_SUCCESS). Funkcja wywołania zwrotnego może przeanalizować zdarzenie i wykonać jakąś operację na ładunku danych. Jeśli chcesz kontynuować korzystanie z istniejącego magazynu redux, możesz zarejestrować wywołanie zwrotne zdarzeń wysyłające akcje do sklepu.

import { PublicClientApplication, EventType } from "@azure/msal-browser";
import { store } from "your-redux-store-implementation";

const msalInstance = new PublicClientApplication(config);

const callbackId = msalInstance.addEventCallback((message: EventMessage) => {
    if (message.eventType === EventType.LOGIN_SUCCESS) {
        store.dispatchAction({type: "AAD_LOGIN_SUCCESS", payload: message.payload});
    }
});

Ładunki danych mogą się różnić między msal v1 a @azure/msal-browser, dlatego może być konieczne wprowadzenie pewnych dostosowań, jeśli aplikacja korzysta z określonych pól lub struktury obiektu. Nasza dokumentacja TypeDoc zawiera najnowszą listę typów zdarzeń i typów ładunku, a mapowanie między nimi można znaleźć w dokumentacji zdarzeń.

Zobacz także