Aan de slag met MSAL React

In dit artikel wordt uitgelegd hoe u aan de slag kunt gaan met @azure/msal-react. We behandelen initialisatie, het bepalen of een gebruiker is geverifieerd, onderdelen beveiligt, een gebruiker aanmeldt en een toegangstoken verkrijgt.

Prerequisites

Initialisatie

@azure/msal-react is gebouwd op de React-context-API en alle onderdelen van uw app waarvoor verificatie is vereist, moeten in het MsalProvider onderdeel worden verpakt. U moet eerst een instantie van PublicClientApplicationinitialiseren en deze vervolgens als prop doorgeven aan MsalProvider.

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 componenten onder MsalProvider hebben via de context toegang tot de PublicClientApplication-instantie en tot alle hooks en componenten die door @azure/msal-reactworden geleverd.

Bepalen of een gebruiker is geverifieerd

De meeste toepassingen moeten bepaalde onderdelen voorwaardelijk weergeven op basis van of een gebruiker al dan niet is aangemeld. @azure/msal-react biedt twee eenvoudige manieren om dit te doen.

AuthenticatedTemplate en UnauthenticatedTemplate

AuthenticatedTemplate en UnauthenticatedTemplate onderdelen geven hun kinderen alleen weer als een gebruiker wordt geverifieerd of niet-geverifieerd.

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 haak

Als alternatief voor de wrapper-onderdelen boven uw app kan de useIsAuthenticated hook worden gebruikt. Meer informatie hierover vindt u 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>
    );
}

Onderdelen beveiligen

Als u onderdelen hebt die u alleen wilt weergeven voor geverifieerde gebruikers, kunt u een van de bovenstaande methoden gebruiken. Maar wat als u automatisch een aanmelding wilt aanroepen als een gebruiker nog niet is geverifieerd? @azure/msal-react biedt 2 manieren om dit te doen met de MsalAuthenticationTemplate of de useMsalAuthentication haak.

MsalAuthenticationTemplate bestanddeel

De MsalAuthenticationTemplate component rendert de onderliggende elementen als een gebruiker is geauthenticeerd of probeert een gebruiker aan te melden. Geef het op met het interactietype dat u wilt gebruiken (omleiden of pop-up) en eventueel een aanvraagobject dat moet worden doorgegeven aan de aanmeldings-API, een onderdeel dat moet worden weergegeven terwijl verificatie wordt uitgevoerd of een onderdeel dat moet worden weergegeven als er een fout optreedt.

U vindt hier een werkend voorbeeld van in een van onze voorbeelden op de /profile pagina.

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 Haak

De useMsalAuthentication hook controleert eerst of een gebruiker is aangemeld en probeert vervolgens een gebruiker aan te melden als er geen gebruikers zijn aangemeld. U moet het interactietype opgeven dat u wilt gebruiken (omleiding of pop-up). Het retourneert het resultaat van de aanmeldingsbewerking, eventuele fouten die zijn opgetreden en de aanmeldingsfunctie die u kunt gebruiken als u het opnieuw moet proberen.

U kunt meer lezen over deze hook in de documentatie over 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>
    );
}

Een gebruiker aanmelden met behulp van de aanmeldings-API's van @azure/msal-browser

Een andere manier om een aanmelding te starten, is door rechtstreeks de @azure/msal-browser API's te gebruiken vanuit de PublicClientApplication instantie in de context. Er zijn drie manieren waarop u toegang hebt tot het exemplaar vanuit context.

useMsal haak

Een hook die het PublicClientApplication exemplaar retourneert, een matrix van alle accounts die momenteel zijn aangemeld en een inProgress waarde die aangeeft wat msal momenteel doet.

U kunt meer lezen over deze hook in de hook-documentatie.

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

De onbewerkte context gebruiken

Als u een klasseonderdeel gebruikt en geen hooks kunt gebruiken, kunt u de onbewerkte msal-context gebruiken via MsalContext. Meer informatie over het gebruik @azure/msal-react in klasseonderdelen vindt u 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>
                </>
            );
        }
    }
}

Je component wrappen met de withMsal Higher-Order Component

Een andere manier om de MSAL-context in zowel klasse- als functieonderdelen te gebruiken, is door uw onderdeel te verpakken met de withMsal HOC die de context in de props van uw onderdeel injecteert.

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

Een toegangstoken verkrijgen

Het is raadzaam dat uw app de acquireTokenSilent API op uw PublicClientApplication object aanroept telkens wanneer u een toegangstoken nodig hebt om toegang te krijgen tot een API. Dit kan vergelijkbaar zijn met de manieren die in de vorige sectie zijn beschreven.

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

Een toegangstoken buiten een React-onderdeel verkrijgen

Als u een toegangstoken buiten een React-onderdeel nodig hebt, kunt u de acquireTokenSilent functie rechtstreeks aanroepen op de PublicClientApplication. We raden u niet aan om functies aan te roepen die de geverifieerde status van de gebruiker wijzigen (aanmelden, afmelden) buiten de react-context die wordt geleverd omdat MsalProvider de onderdelen in de context mogelijk niet correct worden bijgewerkt.

Houd er rekening mee dat de gebruiker moet worden aangemeld voordat u een token kunt verkrijgen.

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

Zie ook