Guia de migração da MSAL v1 para @azure/msal-react e @azure/msal-browser

Este artigo fornece uma visão geral sobre como migrar da MSAL v1 para @azure/msal-react e @azure/msal-browser. Recomendamos a migração para melhor desempenho e melhor segurança com o fluxo de código de autorização com PKCE e Acesso Condicional. Além disso, há um melhor suporte a aplicativos de página única.

Pré-requisitos

  • Uma conta do Azure com uma assinatura ativa. Crie uma conta gratuitamente
  • Um aplicativo existente registrado no seu locatário do Microsoft Entra.

Atualizando o registro do aplicativo

A biblioteca @azure/msal-react é um invólucro em torno de @azure/msal-browser, que implementa o Fluxo de Código de Autorização com PKCE. Essa é uma atualização significativa da biblioteca MSAL v1 que implementa o Fluxo Implícito.

Você precisará criar um novo registro de aplicativo ou atualizar um existente para usar o novo redirectUri tipo "SPA". Consulte o aplicativo de página única: registro de aplicativo para obter mais informações.

Instalando @azure/msal-react e @azure/msal-browser

Tanto @azure/msal-react quanto sua dependência de par @azure/msal-browser podem ser instaladas via npm. É importante desinstalar seu pacote MSAL antigo. Abra um terminal e execute os comandos a seguir.

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

Atualizando de react-aad-msal

Se seu aplicativo atualmente usa o React Microsoft Entra MSAL para autenticação e você está procurando migrar para @azure/msal-react esta seção, descreverá as diferenças entre as duas bibliotecas e algumas das alterações que você precisa fazer. React Microsoft Entra MSAL é uma biblioteca de terceiros e, embora a MSAL React tenha sido desenvolvida do zero, pode haver alguns casos extremos que não sejam cobertos ou suportados pela MSAL React.

A seguir estão os recursos compatíveis com react-aad-msal, mas não com @azure/msal-react:

  • Verificando a expiração do IdToken antes de renderizar componentes protegidos e a atualização automática de IdTokens expirados
  • Suporte pronto para redux store (alternativa abaixo)

Para outros casos possíveis com react-aad-msal, mas que não são mais possíveis com @azure/msal-react, abra um problema no repositório do GitHub microsoft-authentication-library-for-js.

Inicialização

Em react-aad-msal, você inicializa sua instância do MSAL criando um objeto MsalAuthProvider que depois é passado para o componente AzureAD.

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

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

Em @azure/msal-react, você inicializa sua instância do MSAL usando PublicClientApplication, exportado de @azure/msal-browser, que é então passada para o componente MsalProvider, exportado de @azure/msal-react. As opções de configuração são em grande parte semelhantes entre msal e @azure/msal-browser, no entanto, você pode se referir ao tipo de configuração para obter as opções de configuração mais atualizadas.

Os parâmetros authenticationParameters e options usados em react-aad-msal não são usados em @azure/msal-react, embora funcionalidade semelhante possa ser alcançada em componentes individuais. Isso será explicado posteriormente neste documento.

@azure/msal-react usa a API de Contexto do React para disponibilizar PublicClientApplication e o estado de autenticação em toda a sua árvore de componentes.

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

Notas gerais sobre o MsalProvider componente:

  • Todos os componentes que precisam de acesso ao estado de autenticação ou aos hooks/componentes expostos por @azure/msal-react devem ter um MsalProvider mais acima na árvore de componentes; portanto, é recomendável que MsalProvider seja renderizado o mais próximo possível da raiz.
  • Seu aplicativo não deve renderizar mais de 1 MsalProvider componente em uma determinada página.
  • Não recomendamos inicializar PublicClientApplication dentro de um componente devido à possibilidade de re-renderizações

Protegendo seus componentes

Em react-aad-msal, os componentes são protegidos usando o componente AzureAD ou o HOC withAuthentication, que encapsula seu componente com AzureAD internamente. O componente AzureAD só renderizará componentes filho se um usuário estiver autenticado e, opcionalmente, iniciará o login se não houver nenhum usuário autenticado. As opções usadas para login (por exemplo, escopos, se deve usar pop-up ou redirecionamento etc.) são especificadas anteriormente, ao criar a propriedade 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, por outro lado, dá aos desenvolvedores mais controle sobre o que eles querem exibir para quem.

  • O AuthenticatedTemplate componente renderizará filhos se um usuário for autenticado
  • O UnauthenticatedTemplate componente renderizará filhos se um usuário não for autenticado
  • O MsalAuthenticationTemplate componente iniciará automaticamente um logon se um usuário não for autenticado e renderizará os filhos depois que um usuário for autenticado.
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>
    );
}

Além disso, se você preferir adotar uma abordagem baseada em hooks, @azure/msal-react oferece vários hooks que você pode usar para alcançar resultados semelhantes. Esses são apenas alguns exemplos básicos e você pode consultar os ganchos do MSAL React para obter mais informações.

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

Adquirir um token de acesso

react-aad-msal expõe um getAccessToken método que você pode usar para obter um token de acesso antes de chamar uma API.

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

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

Ao usar @azure/msal-react e @azure/msal-browser você chamará acquireTokenSilent na PublicClientApplication instância.

Se você precisar obter um token de acesso dentro de um componente ou hook que esteja em MsalProvider, poderá usar o hook useMsal para obter os objetos necessários.

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

Se você precisar obter um token de acesso fora do contexto de MsalProvider, você pode usar a instância PublicClientApplication diretamente e chamar getAllAccounts() para obter o objeto da conta.

Importante

Tente adquirir o token silenciosamente apenas fora do contexto de MsalProvider. Você não deve chamar um método interativo (redirecionamento ou pop-up) fora do contexto de MsalProvider.

O exemplo a seguir mostra a inicialização de PublicClientApplication para fins de demonstração. PublicClientApplication deve ser inicializado apenas uma vez por carregamento de página e você deve usar a mesma instância aqui que você fornecer para 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;
}

Adquirir um token de ID

react-aad-msal expôs uma getIdToken função para obter ou renovar um idToken.

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

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

Você talvez também conheça o padrão de solicitar seu clientId como o único escopo para obter um idToken. Esse não é mais um padrão com suporte em @azure/msal-browser.

Em @azure/msal-react e @azure/msal-browser, todas as chamadas de token retornarão tanto um token de acesso quanto um token de ID, e todas as renovações de token de acesso também renovarão o token de ID.

Se você precisar obter um token de ID dentro de um componente ou hook que está em MsalProvider, poderá usar o hook useMsal para obter os objetos necessários.

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

Se você precisar obter um token de ID fora do contexto de MsalProvider, poderá usar a instância PublicClientApplication diretamente e chamar getAllAccounts() para obter o objeto da conta.

Importante

Tente adquirir o token silenciosamente apenas fora do contexto de MsalProvider. Você não deve chamar um método interativo (redirecionamento ou pop-up) fora do contexto de MsalProvider.

O exemplo abaixo mostra a inicialização de PublicClientApplication para fins de demonstração. PublicClientApplication deve ser inicializado apenas uma vez a cada carregamento da página, e você deve usar aqui a mesma instância que fornece para 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;
}

Atualizando a integração do repositório redux/reagindo a eventos

react-aad-msal fornecia integração pronta com um repositório do redux, despachando ações quando eventos como login ou logout ocorriam. @azure/msal-react não fornece esse recurso, no entanto, funcionalidades semelhantes podem ser obtidas usando a API de eventos exposta por @azure/msal-browser.

Você pode registrar um callback de evento que será chamado sempre que um evento for disparado (por exemplo, LOGIN_SUCCESS). Sua função de callback pode inspecionar o evento e fazer algo com o payload. Se você quiser continuar usando seu repositório redux existente, poderá registrar um callback de evento que despacha ações para seu repositório.

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

Os conteúdos podem ser diferentes entre msal v1 e @azure/msal-browser , portanto, talvez seja necessário fazer alguns ajustes se o aplicativo depender de campos específicos ou da forma do objeto. Nossos typedocs contêm a lista mais atualizada de tipos de eventos e tipos de conteúdo e você pode encontrar o mapeamento entre os dois no documento de evento.

Consulte também