Condividi tramite


Esercitazione: Chiamare l'API Microsoft Graph in un'app daemon console Node.js

In questa esercitazione viene compilata un'app daemon console che chiama l'API Microsoft Graph usando la propria identità. L'app daemon compilata usa Microsoft Authentication Library (MSAL) per Node.js.

Seguire i passaggi descritti in questa esercitazione per:

  • Registrare l'applicazione nel portale di Azure
  • Creare un progetto di app daemon console Node.js
  • Aggiungere la logica di autenticazione all'app
  • Aggiungere i dettagli di registrazione dell'app
  • Aggiungere un metodo per chiamare un'API Web
  • Testare l'app

Prerequisiti

Registrare l'applicazione

Innanzitutto, completare i passaggi descritti in Registrare un'applicazione con Microsoft Identity Platform per registrare l'app.

Usare le impostazioni seguenti per la registrazione dell'app:

  • Nome: NodeDaemonApp (consigliato)
  • Tipi di account supportati: Account solo in questa directory organizzativa
  • Autorizzazioni delle API: API Microsoft>Microsoft Graph>autorizzazioni dell'applicazione>User.Read.All
  • Segreto client: ********* (registrare questo valore da usare in un passaggio successivo: viene visualizzato una sola volta)

Creare il progetto

  1. Iniziare creando una directory per questo progetto dell’esercitazione su Node.js. Ad esempio, NodeDaemonApp.

  2. Nel terminale passare alla directory creata (la radice del progetto) e quindi eseguire i comandi seguenti:

    npm init -y
    npm install --save dotenv yargs axios @azure/msal-node
    
  3. Poi modificare il file package.json nella radice del progetto e sostituire il valore del prefisso main con bin/ come mostrato di seguito:

    "main": "bin/index.js",
    
  4. Creare ora la directory bin e all'interno di bin, aggiungere il codice seguente a un nuovo file denominato 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();
    

Il file index.js appena creato fa riferimento ad altri due moduli del nodo che verranno creati più avanti:

  • auth.js : usa MSAL Node per acquisire i token di accesso da Microsoft Identity Platform.
  • fetch.js : richiede dati dall'API Microsoft Graph includendo i token di accesso (acquisiti in auth.js) nelle richieste HTTP all'API.

Alla fine dell'esercitazione, la struttura del file e della directory del progetto sarà simile alla seguente:

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

Aggiungere la logica di autenticazione

All'interno della directory bin aggiungere il codice seguente a un nuovo file denominato auth.js. Il codice in auth.js acquisisce un token di accesso da Microsoft Identity Platform da includere nelle richieste API 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
};

Nel frammento di codice precedente prima verrà creato un oggetto di configurazione (msalConfig) che poi verrà passato per inizializzare ConfidentialClientApplication MSAL. Si crea quindi un metodo per acquisire i token tramite credenziali client e infine si espone questo modulo per l'accesso a main.js. I parametri di configurazione in questo modulo vengono recuperati da un file di ambiente, che verrà creato nel passaggio successivo.

Aggiungere i dettagli di registrazione dell'app

Creare un file di ambiente per archiviare i dettagli di registrazione dell'app che verranno usati durante l'acquisizione dei token. A tale scopo creare un file denominato .env all'interno della cartella radice dell'esempio (NodeDaemonApp) e aggiungere il codice seguente:

# 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/

Compilare questi dettagli con i valori ottenuti dal portale di registrazione delle app di Azure:

  • Enter_the_Tenant_Id_here deve essere uno dei seguenti:
    • Se l'applicazione supporta account in questa directory organizzativa, sostituire questo valore con l'ID 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.
  • l' Enter_the_Application_Id_HereID applicazione (client) dell'applicazione registrata.
  • Enter_the_Cloud_Instance_Id_Here: l'istanza del cloud di Azure in cui è 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_Graph_Endpoint_Here è l'istanza dell'API Microsoft Graph con cui l'applicazione dovrà comunicare.
    • 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.

Aggiungere un metodo per chiamare un'API Web

All'interno della cartella bin creare un altro file denominato fetch.js e aggiungere il codice seguente per effettuare chiamate REST all'API 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
};

In questo caso il metodo viene usato percallApieffettuare una richiesta HTTPGET su una risorsa protetta che richiede un token di accesso. La richiesta restituisce quindi il contenuto al chiamante. Questo metodo aggiunge il token acquisito nell'intestazione di autorizzazione HTTP. La risorsa protetta qui è l' endpoint utenti dell'API Microsoft Graph che visualizza gli utenti nel tenant in cui è registrata l'app.

Testare l'app

La creazione dell'applicazione è stata completata ed è ora possibile testare le funzionalità dell'app.

Avviare il l’app daemon console Node.js eseguendo i comandi seguenti all'interno della radice della cartella del progetto:

node . --op getUsers

Il risultato sarà una risposta JSON dall'API Microsoft Graph e nella console verrà visualizzata una matrice di oggetti utente:

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

Visualizzazione della risposta di Graph nell’Interfaccia della riga di comando

Funzionamento dell'applicazione

Questa applicazione usa la concessione delle credenziali client OAuth 2.0. Questo tipo di concessione viene comunemente usato per le interazioni da server a server che devono essere eseguite in background, senza l'interazione immediata con un utente. Il flusso di concessione delle credenziali client consente a un servizio Web (client riservato) di usare le proprie credenziali per l'autenticazione, anziché rappresentare un utente, quando effettua la chiamata a un altro servizio Web. Di solito il tipo di applicazioni supportate con questo modello di autenticazione sono daemon o account di servizio.

L'ambito da richiedere per un flusso di credenziali client è il nome della risorsa seguito da /.default. Questa notazione indica a Microsoft Entra ID di usare le autorizzazioni a livello di applicazione dichiarate in modo statico durante la registrazione dell'applicazione. Inoltre, queste autorizzazioni API devono essere concesse da un amministratore tenant.

Passaggi successivi

Per approfondimenti sull’app daemon console Node.js e lo sviluppo su Microsoft Identity Platform, vedere la serie di scenari in più parti: