Tutorial: Entre em usuários e chame a API do Microsoft Graph a partir de um aplicativo de página única (SPA) JavaScript usando o fluxo de código de autenticação

Neste tutorial, você cria um aplicativo de página única (SPA) JavaScript que entra em usuários e chama o Microsoft Graph usando o fluxo de código de autorização com PKCE. O SPA que você cria usa a Microsoft Authentication Library (MSAL) para JavaScript v2.0.

Neste tutorial:

  • Execute o fluxo de código de autorização do OAuth 2.0 com PKCE
  • Iniciar sessão em contas Microsoft pessoais, bem como em contas escolares e profissionais
  • Adquirir um token de acesso
  • Chame o Microsoft Graph ou sua própria API que requer tokens de acesso obtidos da plataforma de identidade da Microsoft

MSAL.js 2.0 melhora o MSAL.js 1.0 suportando o fluxo de código de autorização no navegador em vez do fluxo de concessão implícito. MSAL.js 2.0 NÃO suporta o fluxo implícito.

Pré-requisitos

  • Node.js para executar um servidor Web local
  • Visual Studio Code ou outro editor de código

Como funciona o aplicativo tutorial

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

O aplicativo criado neste tutorial permite que um SPA JavaScript consulte a API do Microsoft Graph adquirindo tokens de segurança da plataforma de identidade da Microsoft. Nesse cenário, depois que um usuário entra, um token de acesso é solicitado e adicionado a solicitações HTTP no cabeçalho de autorização. A aquisição e renovação de tokens são tratadas pela Biblioteca de Autenticação da Microsoft para JavaScript (MSAL.js).

Este tutorial usa MSAL.js, o pacote de navegador Microsoft Authentication Library for JavaScript v2.0.

Obtenha o exemplo de código concluído

Em vez disso, você pode baixar o projeto de exemplo concluído deste tutorial clonando o repositório ms-identity-javascript-v2 .

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

Para executar o projeto baixado em seu ambiente de desenvolvimento local, comece criando um servidor localhost para seu aplicativo, conforme descrito na etapa 1 de criar seu projeto. Uma vez feito, você pode configurar o exemplo de código pulando para a etapa de configuração.

Para continuar com o tutorial e criar o aplicativo por conta própria, vá para a próxima seção, Criar seu projeto.

Criar o seu projeto

Depois de ter Node.js instalado, crie uma pasta para hospedar seu aplicativo, como msal-spa-tutorial.

Em seguida, implemente um pequeno servidor Web Express para servir seu arquivo index.html .

  1. Primeiro, mude para o diretório do projeto no terminal e, em seguida, execute os seguintes npm comandos:

    npm init -y
    npm install @azure/msal-browser
    npm install express
    npm install morgan
    npm install yargs
    
  2. Em seguida, crie o arquivo chamado server.js e adicione o seguinte código:

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

Criar a interface do usuário do SPA

  1. Crie uma pasta de aplicativo no diretório do projeto e, nela, crie um arquivo de index.html para seu SPA JavaScript. Esse arquivo implementa uma interface do usuário criada com o Bootstrap 4 Framework e importa arquivos de script para configuração, autenticação e chamadas de API.

    No arquivo index.html, adicione o seguinte código:

    <!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. Em seguida, também na pasta do aplicativo , crie um arquivo chamado ui.js e adicione o código a seguir. Esse arquivo acessará e atualizará os elementos DOM.

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

Registar a aplicação

Siga as etapas em Aplicativo de página única: Registro de aplicativo para criar um registro de aplicativo para seu SPA.

Na etapa Redirecionar URI: MSAL.js 2.0 com fluxo de código de autenticação, digite http://localhost:3000, o local padrão onde o aplicativo deste tutorial é executado.

Se pretender utilizar uma porta diferente, introduza http://localhost:<port>, onde <port> é o seu número de porta TCP preferido. Se você especificar um número de porta diferente do , atualize também server.js com o número da porta de 3000sua preferência.

Configurar seu SPA JavaScript

Crie um arquivo chamado authConfig.js na pasta do aplicativo para conter seus parâmetros de configuração para autenticação e adicione o seguinte código:

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

Ainda na pasta do aplicativo , crie um arquivo chamado graphConfig.js. Adicione o seguinte código para fornecer ao seu aplicativo os parâmetros de configuração para chamar a API do Microsoft Graph:

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

Modifique os graphConfig valores na seção conforme descrito aqui:

  • Enter_the_Graph_Endpoint_Here é a instância da API do Microsoft Graph com a qual o aplicativo deve se comunicar.
    • Para o ponto de extremidade global da API do Microsoft Graph, substitua ambas as instâncias dessa cadeia de caracteres por https://graph.microsoft.com.
    • Para pontos de extremidade em implantações de nuvem nacionais, consulte Implantações de nuvem nacional na documentação do Microsoft Graph.

Os graphMeEndpoint valores e graphMailEndpoint em seu graphConfig.js devem ser semelhantes aos seguintes se você estiver usando o ponto de extremidade global:

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

Usar a Biblioteca de Autenticação da Microsoft (MSAL) para entrar no usuário

Pop-up

Na pasta do aplicativo , crie um arquivo chamado authPopup.js e adicione o seguinte código de autenticação e aquisição de token para o pop-up de login:

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

Redirecionamento

Crie um arquivo chamado authRedirect.js na pasta do aplicativo e adicione o seguinte código de autenticação e aquisição de token para redirecionamento de login:

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

Como funciona o código

Quando um usuário seleciona o botão Entrar pela primeira vez, o signIn método chama loginPopup para entrar no usuário. O loginPopup método abre uma janela pop-up com o ponto de extremidade da plataforma de identidade da Microsoft para solicitar e validar as credenciais do usuário. Após uma entrada bem-sucedida, msal.js inicia o fluxo de código de autorização.

Neste ponto, um código de autorização protegido por PKCE é enviado para o ponto de extremidade de token protegido por CORS e é trocado por tokens. Um token de ID, token de acesso e token de atualização são recebidos pelo seu aplicativo e processados por msal.js, e as informações contidas nos tokens são armazenadas em cache.

O token de ID contém informações básicas sobre o usuário, como seu nome para exibição. Se você planeja usar quaisquer dados fornecidos pelo token de ID, seu servidor back-end deve validá-los para garantir que o token foi emitido para um usuário válido para seu aplicativo.

O token de acesso tem uma vida útil limitada e expira após 24 horas. O token de atualização pode ser usado para adquirir silenciosamente novos tokens de acesso.

O SPA que você criou neste tutorial chama acquireTokenSilent e/ou acquireTokenPopup para adquirir um token de acesso usado para consultar a API do Microsoft Graph para obter informações de perfil de usuário. Se você precisar de um exemplo que valide o token de ID, consulte o aplicativo de exemplo active-directory-javascript-singlepageapp-dotnet-webapi-v2 no GitHub. O exemplo usa uma API da Web ASP.NET para validação de token.

Obter um token de utilizador interativamente

Após a entrada inicial, seu aplicativo não deve pedir aos usuários que se autentiquem novamente sempre que precisarem acessar um recurso protegido (ou seja, solicitar um token). Para evitar tais solicitações de reautenticação, ligue para acquireTokenSilent. No entanto, há algumas situações em que talvez seja necessário forçar os usuários a interagir com a plataforma de identidade da Microsoft. Por exemplo:

  • Os usuários precisam inserir novamente suas credenciais porque a senha expirou.
  • Seu aplicativo está solicitando acesso a um recurso e você precisa do consentimento do usuário.
  • A autenticação de dois fatores é necessária.

A chamada acquireTokenPopup abre uma janela pop-up (ou redireciona acquireTokenRedirect os utilizadores para a plataforma de identidade da Microsoft). Nessa janela, os usuários precisam interagir confirmando suas credenciais, dando consentimento para o recurso necessário ou concluindo a autenticação de dois fatores.

Obter um token de utilizador automaticamente

O acquireTokenSilent método lida com a aquisição e renovação de tokens sem qualquer interação do usuário. Depois que loginPopup (ou loginRedirect) é executado pela primeira vez, acquireTokenSilent é o método comumente usado para obter tokens usados para acessar recursos protegidos para chamadas subsequentes. (As chamadas para solicitar ou renovar tokens são feitas silenciosamente.) acquireTokenSilent pode falhar em alguns casos. Por exemplo, a senha do usuário pode ter expirado. Seu aplicativo pode lidar com essa exceção de duas maneiras:

  1. Faça uma chamada para imediatamente para acquireTokenPopup disparar um prompt de entrada do usuário. Esse padrão é comumente usado em aplicativos on-line onde não há conteúdo não autenticado no aplicativo disponível para o usuário. O exemplo gerado por essa configuração guiada usa esse padrão.
  2. Indique visualmente ao utilizador que é necessário um início de sessão interativo para que o utilizador possa selecionar a hora certa para iniciar sessão ou para que a aplicação possa voltar a tentar acquireTokenSilent mais tarde. Essa técnica é comumente usada quando o usuário pode usar outras funcionalidades do aplicativo sem ser interrompido. Por exemplo, pode haver conteúdo não autenticado disponível no aplicativo. Nessa situação, o usuário pode decidir quando deseja entrar para acessar o recurso protegido ou atualizar as informações desatualizadas.

Nota

Este tutorial usa os loginPopup métodos e acquireTokenPopup por padrão. Se estiver a utilizar o Internet Explorer, recomendamos que utilize os métodos e devido a um problema conhecido com o loginRedirect Internet Explorer e acquireTokenRedirect janelas pop-up. Para obter um exemplo de como obter o mesmo resultado usando métodos de redirecionamento, consulte authRedirect.js no GitHub.

Chamar a API do Microsoft Graph

Crie o arquivo chamado graph.js na pasta do aplicativo e adicione o seguinte código para fazer chamadas REST à API do Microsoft Graph:

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

No aplicativo de exemplo criado neste tutorial, o callMSGraph() método é usado para fazer uma solicitação HTTP GET em relação a um recurso protegido que requer um token. Em seguida, a solicitação retorna o conteúdo para o chamador. Este método adiciona o token adquirido no cabeçalho HTTP Authorization. No aplicativo de exemplo criado neste tutorial, o recurso protegido é o ponto de extremidade me da API do Microsoft Graph que exibe as informações de perfil do usuário conectado.

Teste a sua aplicação

Você concluiu a criação do aplicativo e agora está pronto para iniciar o servidor Web Node.js e testar a funcionalidade do aplicativo.

  1. Inicie o servidor Web Node.js executando o seguinte comando de dentro da raiz da pasta do projeto:

    npm start
    
  2. No navegador, navegue até http://localhost:3000 ou http://localhost:<port>, onde <port> está a porta na qual o servidor Web está escutando. Deverá ver o conteúdo do ficheiro index.html e o botão Iniciar sessão.

Iniciar sessão na aplicação

Depois que o navegador carregar seu arquivo de index.html , selecione Entrar. Você será solicitado a entrar com a plataforma de identidade da Microsoft:

Web browser displaying sign-in dialog

Na primeira vez que iniciar sessão na sua aplicação, ser-lhe-á pedido que lhe conceda acesso ao seu perfil e inicie sessão:

Content dialog displayed in web browser

Se você concordar com as permissões solicitadas, o aplicativo Web exibirá seu nome de usuário, significando um login bem-sucedido:

Results of a successful sign-in in the web browser

Chamar a API do Graph

Depois de entrar, selecione Consulte Perfil para exibir as informações de perfil de usuário retornadas na resposta da chamada para a API do Microsoft Graph:

Profile information from Microsoft Graph displayed in the browser

Mais informações sobre escopos e permissões delegadas

A API do Microsoft Graph requer o escopo user.read para ler o perfil de um usuário. Por padrão, esse escopo é adicionado automaticamente em todos os aplicativos registrados no centro de administração do Microsoft Entra. Outras APIs para o Microsoft Graph, bem como APIs personalizadas para seu servidor back-end, podem exigir escopos adicionais. Por exemplo, a API do Microsoft Graph requer o escopo Mail.Read para listar o email do usuário.

À medida que você adiciona escopos, os usuários podem ser solicitados a fornecer consentimento adicional para os escopos adicionados.

Se uma API de back-end não exigir um escopo, o que não é recomendado, você poderá usar clientId como escopo nas chamadas para adquirir tokens.

Ajuda e suporte

Se precisar de ajuda, quiser comunicar um problema ou quiser saber mais sobre as suas opções de suporte, consulte Ajuda e suporte para programadores.

Próximos passos