Tutorial: Chamar a API do Microsoft Graph em um aplicativo daemon de console Node.js

Neste tutorial, você cria um aplicativo daemon de console que chama a API do Microsoft Graph usando sua própria identidade. O aplicativo daemon que você cria usa a Biblioteca de Autenticação da Microsoft (MSAL) para Node.js.

Siga as etapas neste tutorial para:

  • Registrar o aplicativo no portal do Azure
  • Criar um projeto de aplicativo daemon de console Node.js
  • Adicionar lógica de autenticação ao seu aplicativo
  • Adicionar detalhes de registo da aplicação
  • Adicionar um método para chamar uma API da Web
  • Testar a aplicação

Pré-requisitos

Registar a candidatura

Primeiro, conclua as etapas em Registrar um aplicativo com a plataforma de identidade da Microsoft para registrar seu aplicativo.

Use as seguintes configurações para o registro do aplicativo:

  • Nome: NodeDaemonApp (sugerido)
  • Tipos de conta suportados: Somente contas neste diretório organizacional
  • Permissões de API: APIs>da Microsoft Permissões de aplicativo do Microsoft Graph>>User.Read.All
  • Segredo do cliente: ********* (registre esse valor para uso em uma etapa posterior - ele é mostrado apenas uma vez)

Criar o projeto

  1. Comece criando um diretório para este projeto tutorial .js nó. Por exemplo, NodeDaemonApp.

  2. No seu terminal, mude para o diretório que você criou (a raiz do projeto) e, em seguida, execute os seguintes comandos:

    npm init -y
    npm install --save dotenv yargs axios @azure/msal-node
    
  3. Em seguida, edite o arquivo package.json na raiz do projeto e prefixe o valor de main with bin/, desta forma:

    "main": "bin/index.js",
    
  4. Agora crie o diretório bin e, dentro do bin, adicione o seguinte código a um novo arquivo chamado index.js:

    #!/usr/bin/env node
    
    // read in env settings
    require('dotenv').config();
    
    const yargs = require('yargs');
    
    const fetch = require('./fetch');
    const auth = require('./auth');
    
    const options = yargs
        .usage('Usage: --op <operation_name>')
        .option('op', { alias: 'operation', describe: 'operation name', type: 'string', demandOption: true })
        .argv;
    
    async function main() {
        console.log(`You have selected: ${options.op}`);
    
        switch (yargs.argv['op']) {
            case 'getUsers':
    
                try {
                    // here we get an access token
                    const authResponse = await auth.getToken(auth.tokenRequest);
    
                    // call the web API with the access token
                    const users = await fetch.callApi(auth.apiConfig.uri, authResponse.accessToken);
    
                    // display result
                    console.log(users);
                } catch (error) {
                    console.log(error);
                }
    
                break;
            default:
                console.log('Select a Graph operation first');
                break;
        }
    };
    
    main();
    

O arquivo index.js que você acabou de criar faz referência a dois outros módulos de nó que você criará a seguir:

  • auth.js - Usa o nó MSAL para adquirir tokens de acesso da plataforma de identidade da Microsoft.
  • fetch.js - Solicita dados da API do Microsoft Graph incluindo tokens de acesso (adquiridos em auth.js) em solicitações HTTP para a API.

No final do tutorial, a estrutura de arquivos e diretórios do seu projeto deve ser semelhante a esta:

NodeDaemonApp/
├── bin
│   ├── auth.js
│   ├── fetch.js
│   ├── index.js
├── package.json
└── .env

Adicionar lógica de autenticação

Dentro do diretório bin , adicione o seguinte código a um novo arquivo chamado auth.js. O código em auth.js adquire um token de acesso da plataforma de identidade da Microsoft para inclusão em solicitações de API do Microsoft Graph.

const msal = require('@azure/msal-node');

/**
 * Configuration object to be passed to MSAL instance on creation.
 * For a full list of MSAL Node configuration parameters, visit:
 * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/configuration.md
 */
const msalConfig = {
    auth: {
        clientId: process.env.CLIENT_ID,
        authority: process.env.AAD_ENDPOINT + '/' + process.env.TENANT_ID,
        clientSecret: process.env.CLIENT_SECRET,
    }
};

/**
 * With client credentials flows permissions need to be granted in the portal by a tenant administrator.
 * The scope is always in the format '<resource>/.default'. For more, visit:
 * https://learn.microsoft.com/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
 */
const tokenRequest = {
    scopes: [process.env.GRAPH_ENDPOINT + '/.default'],
};

const apiConfig = {
    uri: process.env.GRAPH_ENDPOINT + '/v1.0/users',
};

/**
 * Initialize a confidential client application. For more info, visit:
 * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/initialize-confidential-client-application.md
 */
const cca = new msal.ConfidentialClientApplication(msalConfig);

/**
 * Acquires token with client credentials.
 * @param {object} tokenRequest
 */
async function getToken(tokenRequest) {
    return await cca.acquireTokenByClientCredential(tokenRequest);
}

module.exports = {
    apiConfig: apiConfig,
    tokenRequest: tokenRequest,
    getToken: getToken
};

No trecho de código acima, primeiro criamos um objeto de configuração (msalConfig) e o passamos para inicializar um MSAL ConfidentialClientApplication. Em seguida, criamos um método para adquirir tokens através de credenciais de cliente e, finalmente, expomos este módulo para ser acessado por main.js. Os parâmetros de configuração neste módulo são extraídos de um arquivo de ambiente, que criaremos na próxima etapa.

Adicionar detalhes de registo da aplicação

Crie um arquivo de ambiente para armazenar os detalhes de registro do aplicativo que serão usados ao adquirir tokens. Para fazer isso, crie um arquivo chamado .env dentro da pasta raiz do exemplo (NodeDaemonApp) e adicione o seguinte código:

# Credentials
TENANT_ID=Enter_the_Tenant_Id_Here
CLIENT_ID=Enter_the_Application_Id_Here
CLIENT_SECRET=Enter_the_Client_Secret_Here

# Endpoints
AAD_ENDPOINT=Enter_the_Cloud_Instance_Id_Here/
GRAPH_ENDPOINT=Enter_the_Graph_Endpoint_Here/

Preencha estes detalhes com os valores que você obtém do portal de registro de aplicativo do Azure:

  • Enter_the_Tenant_Id_here deve ser um dos seguintes:
    • Se o seu aplicativo oferecer suporte a contas nesse diretório organizacional, substitua esse valor pelo ID do Locatário ou Nome do Locatário. Por exemplo, contoso.microsoft.com.
    • Se seu aplicativo oferecer suporte a contas em qualquer diretório organizacional, substitua esse valor por organizations.
    • Se o seu aplicativo oferecer suporte a contas em qualquer diretório organizacional e contas pessoais da Microsoft, substitua esse valor por common.
    • Para restringir o suporte apenas a contas pessoais da Microsoft, substitua este valor por consumers.
  • Enter_the_Application_Id_Here: O ID do aplicativo (cliente) do aplicativo que você registrou.
  • Enter_the_Cloud_Instance_Id_Here: A instância de nuvem do Azure na qual seu aplicativo está registrado.
    • Para a nuvem principal (ou global) do Azure, insira https://login.microsoftonline.com.
    • Para nuvens nacionais (por exemplo, China), você pode encontrar valores apropriados em Nuvens nacionais.
  • 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.

Adicionar um método para chamar uma API da Web

Dentro da pasta bin , crie outro arquivo chamado fetch.js e adicione o seguinte código para fazer chamadas REST para a API do Microsoft Graph:

const axios = require('axios');

/**
 * Calls the endpoint with authorization bearer token.
 * @param {string} endpoint
 * @param {string} accessToken
 */
async function callApi(endpoint, accessToken) {

    const options = {
        headers: {
            Authorization: `Bearer ${accessToken}`
        }
    };

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

    try {
        const response = await axios.get(endpoint, options);
        return response.data;
    } catch (error) {
        console.log(error)
        return error;
    }
};

module.exports = {
    callApi: callApi
};

Aqui, o callApi método é usado para fazer uma solicitação HTTP GET em relação a um recurso protegido que requer um token de acesso. Em seguida, a solicitação retorna o conteúdo para o chamador. Este método adiciona o token adquirido no cabeçalho HTTP Authorization. O recurso protegido aqui é o ponto de extremidade de usuários da API do Microsoft Graph, que exibe os usuários no locatário onde esse aplicativo está registrado.

Testar a aplicação

Você concluiu a criação do aplicativo e agora está pronto para testar a funcionalidade do aplicativo.

Inicie o aplicativo daemon de console Node.js executando o seguinte comando de dentro da raiz da pasta do projeto:

node . --op getUsers

Isso deve resultar em alguma resposta JSON da API do Microsoft Graph e você deve ver uma matriz de objetos de usuário no console:

You have selected: getUsers
request made to web API at: Fri Jan 22 2021 09:31:52 GMT-0800 (Pacific Standard Time)
{
    '@odata.context': 'https://graph.microsoft.com/v1.0/$metadata#users',
    value: [
        {
            displayName: 'Adele Vance'
            givenName: 'Adele',
            jobTitle: 'Retail Manager',
            mail: 'AdeleV@msaltestingjs.onmicrosoft.com',
            mobilePhone: null,
            officeLocation: '18/2111',
            preferredLanguage: 'en-US',
            surname: 'Vance',
            userPrincipalName: 'AdeleV@msaltestingjs.onmicrosoft.com',
            id: '00aa00aa-bb11-cc22-dd33-44ee44ee44ee'
        }
    ]
}

Command-line interface displaying Graph response

Como funciona a aplicação

Este aplicativo usa a concessão de credenciais de cliente OAuth 2.0. Este tipo de concessão é comumente utilizado para interações de servidor para servidor que têm de ser executadas em segundo plano, sem interação imediata com um utilizador. O fluxo de concessão de credenciais permite que um serviço Web (cliente confidencial) use suas próprias credenciais, em vez de representar um usuário, para autenticar ao chamar outro serviço Web. O tipo de aplicativos suportados com esse modelo de autenticação geralmente são daemons ou contas de serviço.

O escopo para solicitar um fluxo de credenciais de cliente é o nome do recurso seguido por /.default. Essa notação informa ao Microsoft Entra ID para usar as permissões de nível de aplicativo declaradas estaticamente durante o registro do aplicativo. Além disso, essas permissões de API devem ser concedidas por um administrador de locatário.

Próximos passos

Se você quiser se aprofundar no desenvolvimento de aplicativos daemon .js Nó na plataforma de identidade da Microsoft, consulte nossa série de cenários com várias partes: