Esercitazione: Accedere agli utenti e chiamare Microsoft API Graph da un'app a pagina singola (SPA) React usando il flusso di codice di autenticazione
In questa esercitazione viene creata un'applicazione React a pagina singola (SPA) che accede agli utenti e chiama Microsoft Graph usando il flusso di codice di autorizzazione con PKCE. La spa creata usa Microsoft Authentication Library (MSAL) per React.
In questa esercitazione:
- Creare un progetto di React con
npm
- Registrare l'applicazione nel portale di Azure
- Aggiungere il codice per supportare l'accesso e la disconnessione
- Aggiungere il codice per chiamare l'API Microsoft Graph
- Testare l'app
MSAL React supporta il flusso del codice di autorizzazione nel browser anziché il flusso di concessione implicito. MSAL React non supporta il flusso implicito.
Prerequisiti
- Node.js per l'esecuzione di un server Web locale
- Visual Studio Code o un altro editor di codice
Funzionamento dell'app dell'esercitazione
L'applicazione creata in questa esercitazione consente a una React SPA di eseguire query sull'API Graph Microsoft acquisendo token di sicurezza dall'Microsoft Identity Platform. Usa MSAL per React, un wrapper della libreria MSAL.js v2. MSAL React consente React 16 applicazioni per autenticare gli utenti aziendali usando Azure Active Directory (Azure AD) e anche gli utenti con account Microsoft e identità social come Facebook, Google e LinkedIn. La libreria consente inoltre di ottenere l'accesso a servizi cloud Microsoft e a Microsoft Graph.
Per questo scenario, dopo l'accesso di un utente, viene richiesto e aggiunto un token di accesso alle richieste HTTP nell'intestazione dell'autorizzazione. L'acquisizione e il rinnovo dei token vengono gestiti da MSAL per React (MSAL React).
Librerie
Questa esercitazione usa le librerie seguenti:
Libreria | Descrizione |
---|---|
MSAL React | Microsoft Authentication Library per JavaScript React Wrapper |
MSAL Browser | Pacchetto del browser Microsoft Authentication Library per JavaScript v2 |
Ottenere l'esempio di codice completo
Si preferisce invece scaricare il progetto di esempio completo di questa esercitazione? Per eseguire il progetto usando un server Web locale, ad esempio Node.js, clonare il repository ms-identity-javascript-react-spa :
git clone https://github.com/Azure-Samples/ms-identity-javascript-react-spa
Quindi, per configurare l'esempio di codice prima di eseguirlo, procedere con il passaggio di configurazione.
Per continuare con l'esercitazione e compilare manualmente l'applicazione, passare alla sezione successiva, Creare il progetto.
Creare il progetto
Dopo aver installato Node.js , aprire una finestra del terminale e quindi eseguire i comandi seguenti:
npx create-react-app msal-react-tutorial # Create a new React app
cd msal-react-tutorial # Change to the app directory
npm install @azure/msal-browser @azure/msal-react # Install the MSAL packages
npm install react-bootstrap bootstrap # Install Bootstrap for styling
A questo punto è stato eseguito l'avvio di un piccolo progetto di React usando Crea app React. Questo sarà il punto iniziale su cui verrà compilata la parte restante di questa esercitazione. Se si desidera visualizzare le modifiche apportate all'app durante l'esecuzione di questa esercitazione, è possibile eseguire il comando seguente:
npm start
Una finestra del browser deve essere aperta automaticamente all'app. In caso contrario, aprire il browser e passare a http://localhost:3000. Ogni volta che si salva un file con codice aggiornato, la pagina verrà ricaricata in modo da riflettere le modifiche.
Registrare l'applicazione
Seguire la procedura descritta nell'applicazione a pagina singola: registrazione dell'app per creare una registrazione dell'app per la spa usando il portale di Azure.
Nell'URI di reindirizzamento: MSAL.js 2.0 con il passaggio del flusso del codice di autenticazione immettere http://localhost:3000
, il percorso predefinito in cui create-react-app servirà l'applicazione.
Configurare JavaScript SPA
Creare un file denominato authConfig.js nella cartella src per contenere i parametri di configurazione per l'autenticazione e quindi aggiungere il codice seguente:
export const msalConfig = { auth: { clientId: "Enter_the_Application_Id_Here", authority: "Enter_the_Cloud_Instance_Id_Here/Enter_the_Tenant_Info_Here", // This is a URL (e.g. https://login.microsoftonline.com/{your tenant ID}) redirectUri: "Enter_the_Redirect_Uri_Here", }, cache: { cacheLocation: "sessionStorage", // This configures where your cache will be stored storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge } }; // Add scopes here for ID token to be used at Microsoft identity platform endpoints. export const loginRequest = { scopes: ["User.Read"] }; // Add the endpoints here for Microsoft Graph API services you'd like to use. export const graphConfig = { graphMeEndpoint: "Enter_the_Graph_Endpoint_Here/v1.0/me" };
Modificare i valori nella sezione
msalConfig
come descritto di seguito:Nome del valore Informazioni Enter_the_Application_Id_Here
ID applicazione (client) dell'applicazione registrata. Enter_the_Cloud_Instance_Id_Here
Istanza cloud di Azure in cui viene registrata l'applicazione. Per il cloud principale (o globale) di Azure, immettere https://login.microsoftonline.com
. Peri cloud nazionali, ad esempio Cina, è possibile trovare i valori appropriati nella pagina Cloud nazionali.Enter_the_Tenant_Info_Here
Impostare il valore su una delle opzioni seguenti: Se l'applicazione supporta account in questa directory dell'organizzazione, sostituire questo valore con l'ID della directory (tenant) o il nome del tenant (ad esempio, contoso.microsoft.com). Se l'applicazione supporta Account in qualsiasi directory organizzativa, sostituire questo valore con organizations. Se l'applicazione supporta Account in qualsiasi directory organizzativa e account Microsoft personali, sostituire questo valore con common. Per limitare il supporto ai soli account Microsoft personali, sostituire questo valore con consumers. Enter_the_Redirect_Uri_Here
Sostituire con http://localhost:3000. Enter_the_Graph_Endpoint_Here
L'istanza di Microsoft API Graph l'applicazione deve comunicare con. Per l'endpoint API Microsoft Graph globale, sostituire entrambe le istanze di questa stringa con https://graph.microsoft.com
. Per gli endpoint delle distribuzioni di cloud nazionali, vedere Distribuzioni di cloud nazionali nella documentazione di Microsoft Graph.Per altre informazioni sulle opzioni configurabili disponibili, vedere Inizializzare le applicazioni client.
Aprire il file src/index.js e aggiungere le importazioni seguenti:
import "bootstrap/dist/css/bootstrap.min.css"; import { PublicClientApplication } from "@azure/msal-browser"; import { MsalProvider } from "@azure/msal-react"; import { msalConfig } from "./authConfig";
Sotto le importazioni in src/index.js creare un'istanza
PublicClientApplication
usando la configurazione dal passaggio 1.const msalInstance = new PublicClientApplication(msalConfig);
Trovare il componente in src/index.js e eseguire il
<App />
wrapping nelMsalProvider
componente. La funzione di rendering dovrebbe essere simile alla seguente:ReactDOM.render( <React.StrictMode> <MsalProvider instance={msalInstance}> <App /> </MsalProvider> </React.StrictMode>, document.getElementById("root") );
Consentire l'accesso degli utenti
Creare una cartella in src denominata components e creare un file all'interno di questa cartella denominata SignInButton.jsx. Aggiungere il codice da una delle sezioni seguenti per richiamare l'accesso usando una finestra popup o un reindirizzamento full-frame:
Accedere tramite popup
Aggiungere il codice seguente a src/components/SignInButton.jsx per creare un componente pulsante che richiama un account di accesso popup quando selezionato:
import React from "react";
import { useMsal } from "@azure/msal-react";
import { loginRequest } from "../authConfig";
import Button from "react-bootstrap/Button";
function handleLogin(instance) {
instance.loginPopup(loginRequest).catch(e => {
console.error(e);
});
}
/**
* Renders a button which, when selected, will open a popup for login
*/
export const SignInButton = () => {
const { instance } = useMsal();
return (
<Button variant="secondary" className="ml-auto" onClick={() => handleLogin(instance)}>Sign in using Popup</Button>
);
}
Accedere usando i reindirizzamenti
Aggiungere il codice seguente a src/components/SignInButton.jsx per creare un componente pulsante che richiamerà un account di accesso di reindirizzamento quando selezionato:
import React from "react";
import { useMsal } from "@azure/msal-react";
import { loginRequest } from "../authConfig";
import Button from "react-bootstrap/Button";
function handleLogin(instance) {
instance.loginRedirect(loginRequest).catch(e => {
console.error(e);
});
}
/**
* Renders a button which, when selected, will redirect the page to the login prompt
*/
export const SignInButton = () => {
const { instance } = useMsal();
return (
<Button variant="secondary" className="ml-auto" onClick={() => handleLogin(instance)}>Sign in using Redirect</Button>
);
}
Aggiungere il pulsante di accesso
Creare un altro file nella cartella dei componenti denominata PageLayout.jsx e aggiungere il codice seguente per creare un componente della barra di spostamento che conterrà il pulsante di accesso appena creato:
import React from "react"; import Navbar from "react-bootstrap/Navbar"; import { useIsAuthenticated } from "@azure/msal-react"; import { SignInButton } from "./SignInButton"; /** * Renders the navbar component with a sign-in button if a user is not authenticated */ export const PageLayout = (props) => { const isAuthenticated = useIsAuthenticated(); return ( <> <Navbar bg="primary" variant="dark"> <a className="navbar-brand" href="/">MSAL React Tutorial</a> { isAuthenticated ? <span>Signed In</span> : <SignInButton /> } </Navbar> <h5><center>Welcome to the Microsoft Authentication Library For React Tutorial</center></h5> <br /> <br /> {props.children} </> ); };
Aprire ora src/App.js e aggiungere il contenuto esistente con il codice seguente:
import React from "react"; import { PageLayout } from "./components/PageLayout"; function App() { return ( <PageLayout> <p>This is the main app content!</p> </PageLayout> ); } export default App;
L'app ora ha un pulsante di accesso, che viene visualizzato solo per gli utenti non autenticati!
Quando un utente seleziona il pulsante Accedi usando popup o Accedi usando il pulsante Reindirizzamento per la prima volta, il onClick
gestore chiama loginPopup
(o loginRedirect
) per accedere all'utente. Il metodo loginPopup
apre una finestra popup con l'endpoint di Microsoft Identity Platform per la richiesta e la convalida delle credenziali dell'utente. Dopo aver eseguito l'accesso, msal.js avvia il flusso di Codice di autorizzazione.
A questo punto, un codice di autorizzazione protetto da PKCE viene inviato all'endpoint token protetto da CORS e viene sostituito con i token. L'applicazione riceve un token ID, un token di accesso e un token di aggiornamento, che vengono quindi elaborati da msal.js, quindi le informazioni contenute nei token vengono memorizzate nella cache.
Disconnettersi dagli utenti
In src/components creare un file denominato SignOutButton.jsx. Aggiungere il codice da una delle sezioni seguenti per richiamare l'accesso usando una finestra popup o un reindirizzamento full-frame:
Disconnettersi tramite popup
Aggiungere il codice seguente a src/components/SignOutButton.jsx per creare un componente pulsante che richiama un disconnessione popup quando selezionato:
import React from "react";
import { useMsal } from "@azure/msal-react";
import Button from "react-bootstrap/Button";
function handleLogout(instance) {
instance.logoutPopup().catch(e => {
console.error(e);
});
}
/**
* Renders a button which, when selected, will open a popup for logout
*/
export const SignOutButton = () => {
const { instance } = useMsal();
return (
<Button variant="secondary" className="ml-auto" onClick={() => handleLogout(instance)}>Sign out using Popup</Button>
);
}
Disconnettersi usando i reindirizzamenti
Aggiungere il codice seguente a src/components/SignOutButton.jsx per creare un componente pulsante che richiama un disconnessione di reindirizzamento quando selezionato:
import React from "react";
import { useMsal } from "@azure/msal-react";
import Button from "react-bootstrap/Button";
function handleLogout(instance) {
instance.logoutRedirect().catch(e => {
console.error(e);
});
}
/**
* Renders a button which, when selected, will redirect the page to the logout prompt
*/
export const SignOutButton = () => {
const { instance } = useMsal();
return (
<Button variant="secondary" className="ml-auto" onClick={() => handleLogout(instance)}>Sign out using Redirect</Button>
);
}
Aggiungere il pulsante di disconnessione
Aggiornare il PageLayout
componente in src/components/PageLayout.jsx per eseguire il rendering del nuovo SignOutButton
componente per gli utenti autenticati. Il codice dovrebbe essere simile al seguente:
import React from "react";
import Navbar from "react-bootstrap/Navbar";
import { useIsAuthenticated } from "@azure/msal-react";
import { SignInButton } from "./SignInButton";
import { SignOutButton } from "./SignOutButton";
/**
* Renders the navbar component with a sign-in button if a user is not authenticated
*/
export const PageLayout = (props) => {
const isAuthenticated = useIsAuthenticated();
return (
<>
<Navbar bg="primary" variant="dark">
<a className="navbar-brand" href="/">MSAL React Tutorial</a>
{ isAuthenticated ? <SignOutButton /> : <SignInButton /> }
</Navbar>
<h5><center>Welcome to the Microsoft Authentication Library For React Tutorial</center></h5>
<br />
<br />
{props.children}
</>
);
};
Componenti di rendering condizionale
Per eseguire il rendering di determinati componenti solo per gli utenti autenticati o non autenticati, usare e AuthenticateTemplate
/o UnauthenticatedTemplate
come illustrato di seguito.
Aggiungere l'importazione seguente a src/App.js:
import { AuthenticatedTemplate, UnauthenticatedTemplate } from "@azure/msal-react";
Per eseguire il rendering di determinati componenti solo per gli utenti autenticati, aggiornare la
App
funzione in src/App.js con il codice seguente:function App() { return ( <PageLayout> <AuthenticatedTemplate> <p>You are signed in!</p> </AuthenticatedTemplate> </PageLayout> ); }
Per eseguire il rendering di determinati componenti solo per utenti non autenticati, ad esempio un suggerimento per l'accesso, aggiornare la
App
funzione in src/App.js con il codice seguente:function App() { return ( <PageLayout> <AuthenticatedTemplate> <p>You are signed in!</p> </AuthenticatedTemplate> <UnauthenticatedTemplate> <p>You are not signed in! Please sign in.</p> </UnauthenticatedTemplate> </PageLayout> ); }
Acquisire un token
Prima di chiamare un'API, ad esempio Microsoft Graph, sarà necessario acquisire un token di accesso. Aggiungere un nuovo componente a src/App.js chiamato
ProfileContent
con il codice seguente:function ProfileContent() { const { instance, accounts, inProgress } = useMsal(); const [accessToken, setAccessToken] = useState(null); const name = accounts[0] && accounts[0].name; function RequestAccessToken() { const request = { ...loginRequest, account: accounts[0] }; // Silently acquires an access token which is then attached to a request for Microsoft Graph data instance.acquireTokenSilent(request).then((response) => { setAccessToken(response.accessToken); }).catch((e) => { instance.acquireTokenPopup(request).then((response) => { setAccessToken(response.accessToken); }); }); } return ( <> <h5 className="card-title">Welcome {name}</h5> {accessToken ? <p>Access Token Acquired!</p> : <Button variant="secondary" onClick={RequestAccessToken}>Request Access Token</Button> } </> ); };
Aggiornare le importazioni in src/App.js in modo che corrispondano al frammento di codice seguente:
import React, { useState } from "react"; import { PageLayout } from "./components/PageLayout"; import { AuthenticatedTemplate, UnauthenticatedTemplate, useMsal } from "@azure/msal-react"; import { loginRequest } from "./authConfig"; import Button from "react-bootstrap/Button";
Infine, aggiungere il nuovo
ProfileContent
componente come figlio delAuthenticatedTemplate
componente inApp
src/App.js. IlApp
componente dovrebbe essere simile al seguente:function App() { return ( <PageLayout> <AuthenticatedTemplate> <ProfileContent /> </AuthenticatedTemplate> <UnauthenticatedTemplate> <p>You are not signed in! Please sign in.</p> </UnauthenticatedTemplate> </PageLayout> ); }
Il codice precedente eseguirà il rendering di un pulsante per gli utenti connessi, consentendo loro di richiedere un token di accesso per Microsoft Graph quando viene selezionato il pulsante.
Dopo l'accesso di un utente, l'app non deve chiedere agli utenti di eseguire nuovamente l'autenticazione ogni volta che devono accedere a una risorsa protetta, ovvero per richiedere un token. Per evitare tali richieste di riutenticazione, chiamare acquireTokenSilent
che cercherà prima un token di accesso memorizzato nella cache, non scaduto, quindi, se necessario, usare il token di aggiornamento per ottenere un nuovo token di accesso. Esistono tuttavia alcune situazioni in cui potrebbe essere necessario forzare gli utenti a interagire con il Microsoft Identity Platform. Ad esempio:
- Gli utenti devono immettere nuovamente le credenziali perché la sessione è scaduta.
- Il token di aggiornamento è scaduto.
- L'applicazione richiede l'accesso a una risorsa per cui è necessario il consenso dell'utente.
- È necessaria l'autenticazione a due fattori.
La chiamata acquireTokenPopup
apre una finestra popup (o acquireTokenRedirect
reindirizza gli utenti all'Microsoft Identity Platform). In questa finestra gli utenti devono interagire confermando le proprie credenziali, fornendo il consenso per la risorsa necessaria o completando l'autenticazione a due fattori.
Se si usa Internet Explorer, è consigliabile usare i metodi loginRedirect
e acquireTokenRedirect
a causa di un problema noto di Internet Explorer con le finestre popup.
Chiamare l'API Microsoft Graph
Creare un file denominato graph.js nella cartella src e aggiungere il codice seguente per effettuare chiamate REST al API Graph Microsoft:
import { graphConfig } from "./authConfig"; /** * Attaches a given access token to a Microsoft Graph API call. Returns information about the user */ export async function callMsGraph(accessToken) { const headers = new Headers(); const bearer = `Bearer ${accessToken}`; headers.append("Authorization", bearer); const options = { method: "GET", headers: headers }; return fetch(graphConfig.graphMeEndpoint, options) .then(response => response.json()) .catch(error => console.log(error)); }
Creare quindi un file denominato ProfileData.jsx in src/components e aggiungere il codice seguente:
import React from "react"; /** * Renders information about the user obtained from Microsoft Graph */ export const ProfileData = (props) => { return ( <div id="profile-div"> <p><strong>First Name: </strong> {props.graphData.givenName}</p> <p><strong>Last Name: </strong> {props.graphData.surname}</p> <p><strong>Email: </strong> {props.graphData.userPrincipalName}</p> <p><strong>Id: </strong> {props.graphData.id}</p> </div> ); };
Aprire quindi src/App.js e aggiungere le importazioni seguenti:
import { ProfileData } from "./components/ProfileData"; import { callMsGraph } from "./graph";
Infine, aggiornare il
ProfileContent
componente in src/App.js per chiamare Microsoft Graph e visualizzare i dati del profilo dopo aver acquisito il token. IlProfileContent
componente dovrebbe essere simile al seguente:function ProfileContent() { const { instance, accounts } = useMsal(); const [graphData, setGraphData] = useState(null); const name = accounts[0] && accounts[0].name; function RequestProfileData() { const request = { ...loginRequest, account: accounts[0] }; // Silently acquires an access token which is then attached to a request for Microsoft Graph data instance.acquireTokenSilent(request).then((response) => { callMsGraph(response.accessToken).then(response => setGraphData(response)); }).catch((e) => { instance.acquireTokenPopup(request).then((response) => { callMsGraph(response.accessToken).then(response => setGraphData(response)); }); }); } return ( <> <h5 className="card-title">Welcome {name}</h5> {graphData ? <ProfileData graphData={graphData} /> : <Button variant="secondary" onClick={RequestProfileData}>Request Profile Information</Button> } </> ); };
Nelle modifiche apportate in precedenza, il callMSGraph()
metodo viene usato per effettuare una richiesta HTTP GET
su una risorsa protetta che richiede un token. La richiesta restituisce quindi il contenuto al chiamante. Questo metodo aggiunge il token acquisito nell'intestazione di autorizzazione HTTP. Nell'applicazione di esempio creata in questa esercitazione la risorsa protetta è l'endpoint me dell'API Microsoft Graph, che visualizza informazioni sul profilo dell'utente connesso.
Testare l'applicazione
La creazione dell'applicazione è stata completata e ora è pronta per avviare il server Web e testare la funzionalità dell'app.
Servire l'app eseguendo il comando seguente all'interno della radice della cartella del progetto:
npm start
Una finestra del browser deve essere aperta automaticamente all'app. In caso contrario, aprire il browser e passare a
http://localhost:3000
. Verrà visualizzata una pagina simile a quella seguente.Selezionare il pulsante di accesso per accedere.
Specificare il consenso per l'accesso all'applicazione
La prima volta che si accede all'applicazione, viene chiesto di concedere l'accesso al proprio profilo e viene eseguito l'accesso:
Se si accettano le autorizzazioni richieste, le applicazioni Web visualizzano il nome, firmando un account di accesso riuscito:
Chiamare l'API Graph
Dopo aver eseguito l'accesso, selezionare See Profile (Vedi profilo) per visualizzare le informazioni del profilo utente restituite in una risposta dalla chiamata all'API Microsoft Graph:
Altre informazioni sugli ambiti e sulle autorizzazioni delegate
L'API Microsoft Graph richiede l'ambito user.read per leggere il profilo dell'utente. Per impostazione predefinita, questo ambito viene aggiunto automaticamente in ogni applicazione registrata nel portale di Azure. Altre API per Microsoft Graph e le API personalizzate per il server di back-end potrebbero richiedere anche altri ambiti. Ad esempio, l'API Microsoft Graph richiede l'ambito Mail.Read per visualizzare la posta elettronica dell'utente.
Quando si aggiungono ambiti, agli utenti potrebbe essere richiesto di fornire un consenso aggiuntivo.
Guida e supporto
Se è necessaria assistenza, si vuole segnalare un problema o si vogliono ottenere informazioni sulle opzioni di supporto, vedere Assistenza e supporto per gli sviluppatori.
Passaggi successivi
Se si vuole approfondire lo sviluppo di applicazioni a pagina singola JavaScript con Microsoft Identity Platform, vedere la serie di scenari in più parti: