Začínáme s MSAL Reactem

V tomto článku se dozvíte, jak začít s @azure/msal-react. Probereme inicializaci a určíme, jestli je uživatel ověřený, chrání komponenty, podepisování uživatele a získání přístupového tokenu.

Předpoklady

Inicializace

@azure/msal-react je založen na React Context API a všechny části aplikace, které vyžadují autentizaci, musí být obaleny komponentou MsalProvider. Nejprve musíte inicializovat instanci PublicClientApplication a poté ji předat do MsalProvider jako vlastnost.

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

Všechny komponenty pod MsalProvider budou mít přístup k instanci PublicClientApplication prostřednictvím kontextu a také ke všem hákům a komponentám poskytovaným @azure/msal-react.

Určení, jestli je uživatel ověřený

Většina aplikací bude muset podmíněně vykreslit určité komponenty na základě toho, jestli je uživatel přihlášený nebo ne. @azure/msal-react poskytuje 2 jednoduché způsoby, jak to udělat.

AuthenticatedTemplate a UnauthenticatedTemplate

AuthenticatedTemplate a UnauthenticatedTemplate komponenty vykreslují jejich podřízené položky pouze v případě, že je uživatel ověřený nebo neověřený.

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 hook

Jako alternativu ke komponentám obálky nad vaší aplikací můžete použít useIsAuthenticated háček. Další informace o tom si můžete přečíst v hookech v MSAL Reactu.

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

Ochrana komponent

Pokud máte komponenty, které chcete zobrazit jenom ověřeným uživatelům, můžete použít některou z výše uvedených metod. Ale co když chcete automaticky vyvolat přihlášení, pokud uživatel ještě není ověřený? @azure/msal-react poskytuje 2 způsoby, jak toho dosáhnout pomocí hooku MsalAuthenticationTemplate nebo useMsalAuthentication.

MsalAuthenticationTemplate součást

Komponenta MsalAuthenticationTemplate zobrazí svůj vnořený obsah, pokud je uživatel přihlášený, nebo se ho pokusí přihlásit. Stačí zadat typ interakce, který chcete použít (přesměrovat nebo automaticky otevírané okno) a volitelně objekt požadavku , který se má předat do přihlašovacího rozhraní API, komponentu, která se má zobrazit, když probíhá ověřování, nebo komponenta, která se má zobrazit, pokud dojde k chybě.

Funkční příklad najdete v některém z našich ukázek na /profile stránce.

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 hook

Hook useMsalAuthentication nejprve zkontroluje, jestli je přihlášený uživatel, a pak se pokusí přihlásit uživatele, pokud nejsou přihlášeni žádní uživatelé. Budete muset uvést typ interakce, který chcete použít (přesměrování nebo vyskakovací okno). Vrátí výsledek operace přihlášení, všechny chyby, ke kterým došlo, a funkci přihlášení, kterou můžete použít, pokud potřebujete akci zopakovat.

Další informace o tomto hooku si můžete přečíst v dokumentaci k hookům.

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

Přihlášení uživatele pomocí přihlašovacích rozhraní API poskytovaných službou @azure/msal-browser

Dalším způsobem, jak vyvolat přihlášení, je použití @azure/msal-browser rozhraní API přímo z PublicClientApplication instance v kontextu. Existují 3 způsoby, jak získat přístup k instanci z kontextu.

useMsal háček

Háček, který vrátí PublicClientApplication instanci, pole všech účtů aktuálně přihlášených a inProgress hodnotu, která vám řekne, co msal právě dělá.

Více informací o tomto hooku si můžete přečíst v dokumentaci k hookům.

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

Využívání nezpracovaného kontextu

Pokud používáte komponentu třídy a nemůžete použít háky, můžete využívat nezpracovaný kontext msal prostřednictvím MsalContext. Další informace o použití @azure/msal-react v komponentách tříd najdete tady.

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

Zabalení komponenty pomocí withMsalkomponenty vyššího řádu

Dalším způsobem, jak pracovat s kontextem MSAL v třídních i funkčních komponentách, je obalit komponentu pomocí withMsal HOC, který vloží kontext do vlastností (props) vaší komponenty.

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

Získání přístupového tokenu

Doporučujeme, aby vaše aplikace pokaždé, když potřebuje přístupový token pro přístup k rozhraní API, volala rozhraní API acquireTokenSilent na objektu PublicClientApplication. To lze provést podobně jako způsoby uvedené v předchozí části.

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

Získání přístupového tokenu mimo komponentu React

Pokud potřebujete přístupový token mimo komponentu React, můžete přímo zavolat funkci acquireTokenSilent na objektu PublicClientApplication. Nedoporučujeme volat funkce, které mění stav autentizace uživatele (přihlášení, odhlášení), mimo kontext React poskytnutý komponentou MsalProvider, protože komponenty uvnitř tohoto kontextu se nemusí správně aktualizovat.

Mějte na paměti, že uživatel musí být přihlášený před získáním 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
};

Viz také