Zelfstudie: Gebruikers aanmelden en de Microsoft Graph API aanroepen vanuit een JavaScript-app met één pagina (SPA) met behulp van de verificatiecodestroom

In deze zelfstudie bouwt u een JavaScript-toepassing met één pagina (SPA) die zich aanmeldt bij gebruikers en die Microsoft Graph aanroepen met behulp van de autorisatiecodestroom met PKCE. De SPA die u bouwt, maakt gebruik van de Microsoft Authentication Library (MSAL) voor JavaScript v2.0.

In deze zelfstudie:

  • De OAuth 2.0-autorisatiecodestroom uitvoeren met PKCE
  • Zowel werk- en schoolaccounts als persoonlijke Microsoft-accounts aanmelden
  • Een toegangstoken verkrijgen
  • Microsoft Graph of uw eigen API aanroepen waarvoor toegangstokens zijn vereist die zijn verkregen via het Microsoft Identity Platform

MSAL.js 2.0 verbetert MSAL.js 1.0 door de autorisatiecodestroom in de browser te ondersteunen in plaats van de impliciete toekenningsstroom. MSAL.js 2.0 biedt GEEN ondersteuning voor de impliciete stroom.

Vereisten

Hoe de zelfstudie-app werkt

Diagram showing the authorization code flow in a single-page application

Met de toepassing die u in deze zelfstudie maakt, kan een JavaScript-BEVEILIGD-WACHTWOORDVERIFICATIE een query uitvoeren op de Microsoft Graph API door beveiligingstokens te verkrijgen van het Microsoft Identity Platform. Wanneer een gebruiker zich aanmeldt, wordt in dit scenario een toegangstoken aangevraagd en toegevoegd aan HTTP-aanvragen in de autorisatie-header. Het ophalen en vernieuwen van tokens worden verwerkt door de Microsoft Authentication Library voor JavaScript (MSAL.js).

In deze zelfstudie wordt gebruikgemaakt van MSAL.js, de Microsoft Authentication Library voor JavaScript v2.0-browserpakket.

Het voltooide codevoorbeeld ophalen

U kunt in plaats daarvan het voltooide voorbeeldproject van deze zelfstudie downloaden door de opslagplaats ms-identity-javascript-v2 te klonen.

git clone https://github.com/Azure-Samples/ms-identity-javascript-v2.git

Als u het gedownloade project wilt uitvoeren in uw lokale ontwikkelomgeving, begint u met het maken van een localhost-server voor uw toepassing, zoals beschreven in stap 1 van het maken van uw project. Als u klaar bent, kunt u het codevoorbeeld configureren door over te slaan naar de configuratiestap.

Als u wilt doorgaan met de zelfstudie en de toepassing zelf wilt maken, gaat u naar de volgende sectie: Uw project maken.

Uw project maken

Zodra u Node.js geïnstalleerd, maakt u een map om uw toepassing te hosten, zoals msal-spa-tutorial.

Implementeer vervolgens een kleine Express-webserver om uw index.html-bestand te leveren.

  1. Ga eerst naar de projectmap in uw terminal en voer de volgende npm-opdrachten uit:

    npm init -y
    npm install @azure/msal-browser
    npm install express
    npm install morgan
    npm install yargs
    
  2. Maak vervolgens het bestand met de naam server.js en voeg de volgende code toe:

    const express = require('express');
    const morgan = require('morgan');
    const path = require('path');
    
    const DEFAULT_PORT = process.env.PORT || 3000;
    
    // initialize express.
    const app = express();
    
    // Initialize variables.
    let port = DEFAULT_PORT;
    
    // Configure morgan module to log all requests.
    app.use(morgan('dev'));
    
    // Setup app folders.
    app.use(express.static('app'));
    
    // Set up a route for index.html
    app.get('*', (req, res) => {
        res.sendFile(path.join(__dirname + '/index.html'));
    });
    
    // Start the server.
    app.listen(port);
    console.log(`Listening on port ${port}...`);
    

Een SPA-gebruikersinterface maken

  1. Maak een app-map in de projectmap en maak een index.html-bestand voor uw JavaScript-SPA. Dit bestand implementeert een UI die is gebouwd met het Bootstrap 4 Framework en importeert scriptbestanden voor configuratie, verificatie en API-aanroepen.

    Voeg in het bestand index. html de volgende code toe:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
      <title>Microsoft identity platform</title>
      <link rel="SHORTCUT ICON" href="./favicon.svg" type="image/x-icon">
    
       <!-- msal.min.js can be used in the place of msal.js; included msal.js to make debug easy -->
      <script src="https://alcdn.msauth.net/browser/2.30.0/js/msal-browser.js"
        integrity="sha384-o4ufwq3oKqc7IoCcR08YtZXmgOljhTggRwxP2CLbSqeXGtitAxwYaUln/05nJjit"
        crossorigin="anonymous"></script>
      
      <!-- adding Bootstrap 4 for UI components  -->
      <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
        integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
      <link rel="SHORTCUT ICON" href="https://c.s-microsoft.com/favicon.ico?v2" type="image/x-icon">
    </head>
    
    <body>
      <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
        <a class="navbar-brand" href="/">Microsoft identity platform</a>
        <div class="btn-group ml-auto dropleft">
          <button type="button" id="SignIn" class="btn btn-secondary" onclick="signIn()">
            Sign In
          </button>
        </div>
      </nav>
      <br>
      <h5 class="card-header text-center">Vanilla JavaScript SPA calling MS Graph API with MSAL.js</h5>
      <br>
      <div class="row" style="margin:auto">
        <div id="card-div" class="col-md-3" style="display:none">
          <div class="card text-center">
            <div class="card-body">
              <h5 class="card-title" id="WelcomeMessage">Please sign-in to see your profile and read your mails</h5>
              <div id="profile-div"></div>
              <br>
              <br>
              <button class="btn btn-primary" id="seeProfile" onclick="seeProfile()">See Profile</button>
              <br>
              <br>
              <button class="btn btn-primary" id="readMail" onclick="readMail()">Read Mails</button>
            </div>
          </div>
        </div>
        <br>
        <br>
        <div class="col-md-4">
          <div class="list-group" id="list-tab" role="tablist">
          </div>
        </div>
        <div class="col-md-5">
          <div class="tab-content" id="nav-tabContent">
          </div>
        </div>
      </div>
      <br>
      <br>
    
      <!-- importing bootstrap.js and supporting js libraries -->
      <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
        integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
        crossorigin="anonymous"></script>
      <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
        integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
        crossorigin="anonymous"></script>
      <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
        integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
        crossorigin="anonymous"></script>
    
      <!-- importing app scripts (load order is important) -->
      <script type="text/javascript" src="./authConfig.js"></script>
      <script type="text/javascript" src="./graphConfig.js"></script>
      <script type="text/javascript" src="./ui.js"></script>
    
      <!-- <script type="text/javascript" src="./authRedirect.js"></script>   -->
      <!-- uncomment the above line and comment the line below if you would like to use the redirect flow -->
      <script type="text/javascript" src="./authPopup.js"></script>
      <script type="text/javascript" src="./graph.js"></script>
    </body>
    
    </html>
    
  2. Maak vervolgens in de app-map een bestand met de naam ui.js en voeg de volgende code toe. Met dit bestand worden DOM-elementen geopend en bijgewerkt.

    // Select DOM elements to work with
    const welcomeDiv = document.getElementById("WelcomeMessage");
    const signInButton = document.getElementById("SignIn");
    const cardDiv = document.getElementById("card-div");
    const mailButton = document.getElementById("readMail");
    const profileButton = document.getElementById("seeProfile");
    const profileDiv = document.getElementById("profile-div");
    
    function showWelcomeMessage(username) {
        // Reconfiguring DOM elements
        cardDiv.style.display = 'initial';
        welcomeDiv.innerHTML = `Welcome ${username}`;
        signInButton.setAttribute("onclick", "signOut();");
        signInButton.setAttribute('class', "btn btn-success")
        signInButton.innerHTML = "Sign Out";
    }
    
    function updateUI(data, endpoint) {
        console.log('Graph API responded at: ' + new Date().toString());
    
        if (endpoint === graphConfig.graphMeEndpoint) {
            profileDiv.innerHTML = ''
            const title = document.createElement('p');
            title.innerHTML = "<strong>Title: </strong>" + data.jobTitle;
            const email = document.createElement('p');
            email.innerHTML = "<strong>Mail: </strong>" + data.mail;
            const phone = document.createElement('p');
            phone.innerHTML = "<strong>Phone: </strong>" + data.businessPhones[0];
            const address = document.createElement('p');
            address.innerHTML = "<strong>Location: </strong>" + data.officeLocation;
            profileDiv.appendChild(title);
            profileDiv.appendChild(email);
            profileDiv.appendChild(phone);
            profileDiv.appendChild(address);
    
        } else if (endpoint === graphConfig.graphMailEndpoint) {
            if (!data.value) {
                alert("You do not have a mailbox!")
            } else if (data.value.length < 1) {
                alert("Your mailbox is empty!")
            } else {
                const tabContent = document.getElementById("nav-tabContent");
                const tabList = document.getElementById("list-tab");
                tabList.innerHTML = ''; // clear tabList at each readMail call
    
                data.value.map((d, i) => {
                    // Keeping it simple
                    if (i < 10) {
                        const listItem = document.createElement("a");
                        listItem.setAttribute("class", "list-group-item list-group-item-action")
                        listItem.setAttribute("id", "list" + i + "list")
                        listItem.setAttribute("data-toggle", "list")
                        listItem.setAttribute("href", "#list" + i)
                        listItem.setAttribute("role", "tab")
                        listItem.setAttribute("aria-controls", i)
                        listItem.innerHTML = d.subject;
                        tabList.appendChild(listItem)
    
                        const contentItem = document.createElement("div");
                        contentItem.setAttribute("class", "tab-pane fade")
                        contentItem.setAttribute("id", "list" + i)
                        contentItem.setAttribute("role", "tabpanel")
                        contentItem.setAttribute("aria-labelledby", "list" + i + "list")
                        contentItem.innerHTML = "<strong> from: " + d.from.emailAddress.address + "</strong><br><br>" + d.bodyPreview + "...";
                        tabContent.appendChild(contentItem);
                    }
                });
            }
        }
    }
    

Uw toepassing registreren

Volg de stappen in de toepassing met één pagina: App-registratie om een app-registratie voor uw BEVEILIGD-WACHTWOORDVERIFICATIE te maken.

Voer http://localhost:3000in de omleidings-URI: MSAL.js 2.0 met de stroomstap voor verificatiecode de standaardlocatie in waar de toepassing van deze zelfstudie wordt uitgevoerd.

Als u een andere poort wilt gebruiken, voert u http://localhost:<port> in, waarbij <port> het voorkeurs-TCP-poortnummer is. Als u een ander poortnummer dan 3000opgeeft, moet u ook server.js met uw voorkeurspoortnummer bijwerken.

Uw JavaScript-SPA configureren

Maak een bestand met de naam authConfig.js in de map app om uw configuratieparameters voor verificatie op te nemen en voeg vervolgens de volgende code toe:

/**
 * Configuration object to be passed to MSAL instance on creation. 
 * For a full list of MSAL.js configuration parameters, visit:
 * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/configuration.md 
 */
const msalConfig = {
    auth: {
        // 'Application (client) ID' of app registration in Azure portal - this value is a GUID
        clientId: "Enter_the_Application_Id_Here",
        // Full directory URL, in the form of https://login.microsoftonline.com/<tenant-id>
        authority: "Enter_the_Cloud_Instance_Id_HereEnter_the_Tenant_Info_Here",
        // Full redirect URL, in form of http://localhost:3000
        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
    },
    system: {	
        loggerOptions: {	
            loggerCallback: (level, message, containsPii) => {	
                if (containsPii) {		
                    return;		
                }		
                switch (level) {		
                    case msal.LogLevel.Error:		
                        console.error(message);		
                        return;		
                    case msal.LogLevel.Info:		
                        console.info(message);		
                        return;		
                    case msal.LogLevel.Verbose:		
                        console.debug(message);		
                        return;		
                    case msal.LogLevel.Warning:		
                        console.warn(message);		
                        return;		
                }	
            }	
        }	
    }
};

/**
 * Scopes you add here will be prompted for user consent during sign-in.
 * By default, MSAL.js will add OIDC scopes (openid, profile, email) to any login request.
 * For more information about OIDC scopes, visit: 
 * https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent#openid-connect-scopes
 */
const loginRequest = {
    scopes: ["User.Read"]
};

/**
 * Add here the scopes to request when obtaining an access token for MS Graph API. For more information, see:
 * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/resources-and-scopes.md
 */
const tokenRequest = {
    scopes: ["User.Read", "Mail.Read"],
    forceRefresh: false // Set this to "true" to skip a cached token and go to the server to get a new token
};

Maak nog in de map app een bestand met de naam graphConfig.js. Voeg de volgende code toe om uw toepassing de configuratieparameters te geven voor het aanroepen van de Microsoft Graph API:

// Add here the endpoints for MS Graph API services you would like to use.
const graphConfig = {
    graphMeEndpoint: "Enter_the_Graph_Endpoint_Herev1.0/me",
    graphMailEndpoint: "Enter_the_Graph_Endpoint_Herev1.0/me/messages"
};

Wijzig de waarden in de sectie graphConfig, zoals hier wordt beschreven:

  • Enter_the_Graph_Endpoint_Here is het exemplaar van de Microsoft Graph API waarmee de toepassing moet communiceren.
    • Vervang beide exemplaren van deze teken reeks door https://graph.microsoft.com voor het wereldwijde Microsoft Graph API-eindpunt.
    • Zie Nationale cloudimplementaties in de Microsoft Graph-documentatie voor eindpunten in nationale cloudimplementaties.

De waarden graphMeEndpoint en graphMailEndpoint in uw authConfig.js moeten er als volgt uitzien als u het wereldwijde eindpunt gebruikt:

graphMeEndpoint: "https://graph.microsoft.com/v1.0/me",
graphMailEndpoint: "https://graph.microsoft.com/v1.0/me/messages"

De Microsoft Authentication Library (MSAL) gebruiken om de gebruiker aan te melden

Pop-up

Maak in de map van de app een bestand met de naam authPopup.js en voeg de volgende code toe voor het verkrijgen van een verificatie en token voor de pop-up van de aanmelding:

// Create the main myMSALObj instance
// configuration parameters are located at authConfig.js
const myMSALObj = new msal.PublicClientApplication(msalConfig);

let username = "";

function selectAccount() {

    /**
     * See here for more info on account retrieval: 
     * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-common/docs/Accounts.md
     */

    const currentAccounts = myMSALObj.getAllAccounts();
    if (currentAccounts.length === 0) {
        return;
    } else if (currentAccounts.length > 1) {
        // Add choose account code here
        console.warn("Multiple accounts detected.");
    } else if (currentAccounts.length === 1) {
        username = currentAccounts[0].username;
        showWelcomeMessage(username);
    }
}

function handleResponse(response) {

    /**
     * To see the full list of response object properties, visit:
     * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/request-response-object.md#response
     */

    if (response !== null) {
        username = response.account.username;
        showWelcomeMessage(username);
    } else {
        selectAccount();
    }
}

function signIn() {

    /**
     * You can pass a custom request object below. This will override the initial configuration. For more information, visit:
     * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/request-response-object.md#request
     */

    myMSALObj.loginPopup(loginRequest)
        .then(handleResponse)
        .catch(error => {
            console.error(error);
        });
}

function signOut() {

    /**
     * You can pass a custom request object below. This will override the initial configuration. For more information, visit:
     * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/request-response-object.md#request
     */

    const logoutRequest = {
        account: myMSALObj.getAccountByUsername(username),
        postLogoutRedirectUri: msalConfig.auth.redirectUri,
        mainWindowRedirectUri: msalConfig.auth.redirectUri
    };

    myMSALObj.logoutPopup(logoutRequest);
}

function getTokenPopup(request) {

    /**
     * See here for more info on account retrieval: 
     * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-common/docs/Accounts.md
     */
    request.account = myMSALObj.getAccountByUsername(username);
    
    return myMSALObj.acquireTokenSilent(request)
        .catch(error => {
            console.warn("silent token acquisition fails. acquiring token using popup");
            if (error instanceof msal.InteractionRequiredAuthError) {
                // fallback to interaction when silent call fails
                return myMSALObj.acquireTokenPopup(request)
                    .then(tokenResponse => {
                        console.log(tokenResponse);
                        return tokenResponse;
                    }).catch(error => {
                        console.error(error);
                    });
            } else {
                console.warn(error);   
            }
    });
}

function seeProfile() {
    getTokenPopup(loginRequest)
        .then(response => {
            callMSGraph(graphConfig.graphMeEndpoint, response.accessToken, updateUI);
        }).catch(error => {
            console.error(error);
        });
}

function readMail() {
    getTokenPopup(tokenRequest)
        .then(response => {
            callMSGraph(graphConfig.graphMailEndpoint, response.accessToken, updateUI);
        }).catch(error => {
            console.error(error);
        });
}

selectAccount();

Omleiden

Maak een bestand met de naam authRedirect.js in de map van de app en voeg de volgende code toe voor het verkrijgen van een verificatie en token toe voor het omleiden van de aanmelding:

// Create the main myMSALObj instance
// configuration parameters are located at authConfig.js
const myMSALObj = new msal.PublicClientApplication(msalConfig);

let username = "";

/**
 * A promise handler needs to be registered for handling the
 * response returned from redirect flow. For more information, visit:
 * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/acquire-token.md
 */
myMSALObj.handleRedirectPromise()
    .then(handleResponse)
    .catch((error) => {
        console.error(error);
    });

function selectAccount () {

    /**
     * See here for more info on account retrieval: 
     * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-common/docs/Accounts.md
     */

    const currentAccounts = myMSALObj.getAllAccounts();

    if (currentAccounts.length === 0) {
        return;
    } else if (currentAccounts.length > 1) {
        // Add your account choosing logic here
        console.warn("Multiple accounts detected.");
    } else if (currentAccounts.length === 1) {
        username = currentAccounts[0].username;
        showWelcomeMessage(username);
    }
}

function handleResponse(response) {
    if (response !== null) {
        username = response.account.username;
        showWelcomeMessage(username);
    } else {
        selectAccount();
    }
}

function signIn() {

    /**
     * You can pass a custom request object below. This will override the initial configuration. For more information, visit:
     * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/request-response-object.md#request
     */

    myMSALObj.loginRedirect(loginRequest);
}

function signOut() {

    /**
     * You can pass a custom request object below. This will override the initial configuration. For more information, visit:
     * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/request-response-object.md#request
     */

    const logoutRequest = {
        account: myMSALObj.getAccountByUsername(username),
        postLogoutRedirectUri: msalConfig.auth.redirectUri,
    };

    myMSALObj.logoutRedirect(logoutRequest);
}

function getTokenRedirect(request) {
    /**
     * See here for more info on account retrieval: 
     * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-common/docs/Accounts.md
     */
    request.account = myMSALObj.getAccountByUsername(username);

    return myMSALObj.acquireTokenSilent(request)
        .catch(error => {
            console.warn("silent token acquisition fails. acquiring token using redirect");
            if (error instanceof msal.InteractionRequiredAuthError) {
                // fallback to interaction when silent call fails
                return myMSALObj.acquireTokenRedirect(request);
            } else {
                console.warn(error);   
            }
        });
}

function seeProfile() {
    getTokenRedirect(loginRequest)
        .then(response => {
            callMSGraph(graphConfig.graphMeEndpoint, response.accessToken, updateUI);
        }).catch(error => {
            console.error(error);
        });
}

function readMail() {
    getTokenRedirect(tokenRequest)
        .then(response => {
            callMSGraph(graphConfig.graphMailEndpoint, response.accessToken, updateUI);
        }).catch(error => {
            console.error(error);
        });
}

Hoe de code werkt

Wanneer een gebruiker de knop Aanmelden voor de eerste keer selecteert, roept de methode signInloginPopup aan om zich aan te melden bij de gebruiker. Met de methode loginPopup wordt een pop-upvenster geopend met het Microsoft-identiteitsplatform-eindpunt om de referenties van de gebruiker te vragen en te valideren. Na een geslaagde aanmelding, initieert msal.js de autorisatiecodestroom.

Op dit moment wordt een met PKCE beveiligde autorisatiecode verzonden naar het eindpunt van het met CORS beveiligde token en wordt deze uitgewisseld voor tokens. Er worden een ID-token, toegangstoken en vernieuwingstoken ontvangen door uw toepassing en verwerkt door msal.js, en de gegevens in de tokens worden in de cache opgeslagen.

Het ID-token bevat basisinformatie over de gebruiker, zoals de weergavenaam. Als u van plan bent om gegevens te gebruiken die worden verstrekt door het ID-token, moet uw back-endserver dit valideren om te garanderen dat het token is uitgegeven aan een geldige gebruiker voor uw toepassing.

Het toegangstoken heeft een beperkte levensduur en verloopt na 24 uur. Het vernieuwingstoken kan worden gebruikt om nieuwe toegangstokens op de achtergrond te verkrijgen.

De SPA die u in deze zelfstudie hebt gemaakt, roept acquireTokenSilent en/of acquireTokenPopup aan om een toegangstoken te verkrijgen dat wordt gebruikt om een query uit te voeren op de Microsoft Graph API voor profielgegevens van gebruikers. Als u een voorbeeld nodig hebt dat het ID-token valideert, raadpleegt u de voorbeeldtoepassing active-directory-javascript-singlepageapp-dotnet-webapi-v2 op GitHub. In het voorbeeld wordt een ASP.NET-web-API gebruikt voor het valideren van tokens.

Een gebruikerstoken interactief ophalen

Na de eerste aanmelding moet uw app gebruikers niet meer vragen om opnieuw te verifiëren voor elke keer dat ze toegang moeten krijgen tot een beveiligde bron (dat wil zeggen, om een token aan te vragen). Roep acquireTokenSilent aan om dergelijke nieuwe verificatieverzoeken te voorkomen. Er zijn echter een aantal situaties waarin u mogelijk wilt afdwingen dat gebruikers met het Microsoft-identiteitsplatform kunnen communiceren. Voorbeeld:

  • Gebruikers moeten mogelijk hun referenties opnieuw opgeven omdat het wachtwoord is verlopen.
  • Uw toepassing vraagt toegang tot een resource waarvoor de gebruiker toestemming moet geven.
  • Verificatie in twee stappen is vereist.

Als u acquireTokenPopup aanroept, wordt een pop-upvenster geopend (of acquireTokenRedirect leidt gebruikers om naar het Microsoft-identiteitsplatform). In dat venster moeten gebruikers hun referenties bevestigen, toestemming geven voor de vereiste resource of verificatie in wee stappen uitvoeren.

Een gebruikerstoken op de achtergrond ophalen

Met de methode acquireTokenSilent wordt het verkrijgen en vernieuwen van tokens verwerkt zonder tussenkomst van de gebruiker. Nadat de methode loginPopup (of loginRedirect) de eerste keer is uitgevoerd, wordt voor volgende aanroepen meestal de methode acquireTokenSilent gebruikt om tokens te verkrijgen die worden gebruikt voor toegang tot beveiligde resources. (Aanroepen naar aanvraag- of vernieuwingstokens worden op de achtergrond uitgevoerd.) acquireTokenSilent kan in sommige gevallen mislukken. Het is bijvoorbeeld mogelijk dat het wachtwoord van de gebruiker is verlopen. Uw toepassing kan deze uitzondering op twee manieren afhandelen:

  1. Een aanroep naar acquireTokenPopup onmiddellijk uitvoeren om een aanmeldingsprompt van een gebruiker te activeren. Dit patroon wordt vaak gebruikt in online toepassingen waarbij er geen niet-geverifieerde inhoud in de toepassing beschikbaar is voor de gebruiker. Het voorbeeld dat door deze begeleide installatie wordt gegenereerd, maakt gebruik van dit patroon.
  2. Visueel aan de gebruiker aangeven door dat een interactieve aanmelding is vereist, zodat de gebruiker de juiste tijd kan selecteren om zich aan te melden, of de toepassing kan acquireTokenSilent op een later tijdstip opnieuw proberen. Deze techniek wordt vaak gebruikt wanneer de gebruiker andere functionaliteit van de toepassing kan gebruiken zonder te worden onderbroken. Het is bijvoorbeeld mogelijk dat er niet-geverifieerde inhoud beschikbaar is in de toepassing. In dit geval kan de gebruiker beslissen wanneer hij of zij zich wil aanmelden om toegang te krijgen tot de beveiligde resource, of om de verouderde informatie te vernieuwen.

Notitie

In deze zelfstudie wordt standaard gebruikgemaakt van de methoden loginPopup en acquireTokenPopup. Als u Internet Explorer gebruikt, raden we u aan de methoden loginRedirect en acquireTokenRedirect te gebruiken vanwege een bekend probleem met Internet Explorer en pop-upvensters. Zie authRedirect.js op GitHub voor een voorbeeld van het bereiken van hetzelfde resultaat met behulp van omleidingsmethoden.

De Microsoft Graph API aanroepen

Maak een bestand met de naam Graph.js in de map van de app en voeg de volgende code toe om REST-aanroepen naar de Microsoft Graph API te brengen:

/** 
 * Helper function to call MS Graph API endpoint
 * using the authorization bearer token scheme
*/
function callMSGraph(endpoint, token, callback) {
    const headers = new Headers();
    const bearer = `Bearer ${token}`;

    headers.append("Authorization", bearer);

    const options = {
        method: "GET",
        headers: headers
    };

    console.log('request made to Graph API at: ' + new Date().toString());

    fetch(endpoint, options)
        .then(response => response.json())
        .then(response => callback(response, endpoint))
        .catch(error => console.log(error));
}

In de voorbeeldtoepassing die in deze zelfstudie wordt gemaakt, wordt de methode callMSGraph() gebruikt om een HTTP GET-aanvraag uit te voeren voor een beveiligde bron waarvoor een token is vereist. De aanvraag retourneert vervolgens de inhoud naar de aanroeper. Met deze methode wordt het verkregen token toegevoegd in de HTTP-autorisatie-header. In de voorbeeldtoepassing die in deze zelfstudie is gemaakt, is de beveiligde resource het Microsoft Graph API me-eindpunt waarin de profielgegevens van de aangemelde gebruiker worden weergegeven.

Uw toepassing testen

Het maken van de toepassing is voltooid en u bent nu klaar om de Node.js-webserver te starten en de functionaliteit van de app te testen.

  1. Start de Node.js-webserver door de volgende opdracht uit te voeren in de hoofdmap van de projectmap:

    npm start
    
  2. Ga in uw browser naar http://localhost:3000 of http://localhost:<port>, waarbij <port> de poort is, waarop uw webserver luistert. U moet de inhoud van uw bestand index.html en de knop Aanmelden zien.

Aanmelden bij Azure Portal

Nadat de browser het bestand index.html heeft geladen, selecteert u Aanmelden. U wordt gevraagd u aan te melden bij het Microsoft identity platform:

Web browser displaying sign-in dialog

De eerste keer dat u zich aanmeldt bij uw toepassing, wordt u gevraagd om deze toegang te geven tot uw profiel en om u aan te melden:

Content dialog displayed in web browser

Als u toestemming geeft voor de aangevraagde machtigingen, geeft de webtoepassing uw gebruikersnaam weer, wat een geslaagde aanmelding aangeeft:

Results of a successful sign-in in the web browser

De Graph API aanroepen

Nadat u zich hebt aangemeld, selecteert u Profiel bekijken om de profielgegevens van de gebruiker weer te geven die zijn geretourneerd in het antwoord van de aanroep van de Microsoft Graph API:

Profile information from Microsoft Graph displayed in the browser

Meer informatie over bereiken en gedelegeerde machtigingen

De Microsoft Graph API vereist het bereik user.read om het profiel van een gebruiker te lezen. Dit bereik wordt standaard automatisch toegevoegd in elke toepassing die is geregistreerd in het Microsoft Entra-beheercentrum. Overige API's voor Microsoft Graph, evenals aangepaste API's voor uw back-endserver, vereisen mogelijk aanvullende bereiken. De Microsoft Graph API vereist bijvoorbeeld het bereik Mail.Read om de e-mail van de gebruiker op te sommen.

Wanneer u scopes toevoegt, kunnen uw gebruikers worden gevraagd om extra toestemming te geven voor de toegevoegde scopes.

Als voor een back-end-API geen bereik is vereist, wat niet aanbevolen wordt, kunt u clientId gebruiken als het bereik in de aanroepen om tokens te verkrijgen.

Help en ondersteuning

Als u hulp nodig hebt, een probleem wilt melden of meer informatie wilt over uw ondersteuningsopties, raadpleegt u Hulp en ondersteuning voor ontwikkelaars.

Volgende stappen

  • Meer informatie vindt u door een React-toepassing met één pagina (SPA) te bouwen waarmee gebruikers worden aangemeld in de volgende reeks meerdelige zelfstudies.