Partager via


Didacticiel : appeler une API web à partir de votre application démon Node.js

Ce tutoriel constitue la dernière partie d’une série qui explique comment préparer votre application cliente démon Node.js en utilisant le flux d’octroi des informations d’identification du client Open Authorization (OAuth) 2.0, puis la configurer afin d’acquérir un jeton d’accès pour appeler une API web. dans la Partie 1 de cette série, vous avez inscrit une API web et une application démon dans le centre d’administration Microsoft Entra et accordé des autorisations. Cette dernière étape montre comment construire une application Node.js en utilisant la Bibliothèque d’authentification Microsoft (MSAL) pour Node afin de simplifier l’ajout d’autorisations à votre application.

Dans ce tutoriel,

  • Créez une application Node.js dans Visual Studio Code, puis installez les dépendances.
  • Activez l’application Node.js afin d’acquérir un jeton d’accès pour appeler une API web.

Prérequis

Créer le projet daemon Node.js

Créez un dossier pour héberger votre application daemon Node.js, par exemple ciam-call-api-node-daemon :

  1. Depuis votre terminal, changez de répertoire pour accéder au dossier de l'application daemon Node, par exemple cd ciam-call-api-node-daemon, et exécutez npm init -y. Cette commande crée un fichier package.json par défaut pour votre projet Node.js. Cette commande crée un fichier package.json par défaut pour votre projet Node.js.

  2. Créez d’autres dossiers et fichiers pour obtenir la structure de projet suivante :

        ciam-call-api-node-daemon/
        ├── auth.js
        └── authConfig.js
        └── fetch.js
        └── index.js 
        └── package.json
    

Installer les dépendances de l’application

Depuis votre terminal, installez les packages axios, yargs et @azure/msal-node, en exécutant les commandes suivantes :

npm install axios yargs @azure/msal-node   

Créer un objet de configuration MSAL

Dans votre éditeur de code, ouvrez le fichier authConfig.js, puis ajoutez le code suivant :

require('dotenv').config();

/**
 * 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 || 'Enter_the_Application_Id_Here', // 'Application (client) ID' of app registration in Azure portal - this value is a GUID
        authority: process.env.AUTHORITY || 'https://Enter_the_Tenant_Subdomain_Here.ciamlogin.com/', // Replace "Enter_the_Tenant_Subdomain_Here" with your tenant subdomain
        clientSecret: process.env.CLIENT_SECRET || 'Enter_the_Client_Secret_Here', // Client secret generated from the app 
    },
    system: {
        loggerOptions: {
            loggerCallback(loglevel, message, containsPii) {
                console.log(message);
            },
            piiLoggingEnabled: false,
            logLevel: 'Info',
        },
    },
};    
const protectedResources = {
    apiToDoList: {
        endpoint: process.env.API_ENDPOINT || 'https://localhost:44351/api/todolist',
        scopes: [process.env.SCOPES || 'api://Enter_the_Web_Api_Application_Id_Here'],
    },
};

module.exports = {
    msalConfig,
    protectedResources,
};

L’objet msalConfig contient un ensemble d’options de configuration à utiliser pour personnaliser le comportement de votre flux d’autorisation.

Dans votre fichier authConfig.js, remplacez :

  • Enter_the_Application_Id_Here avec l’ID d’application (client) de l’application du client daemon inscrite précédemment.

  • Enter_the_Tenant_Subdomain_Here et remplacez par le sous-domaine du répertoire (locataire). Par exemple, si votre domaine principal du locataire est contoso.onmicrosoft.com, utilisez contoso. Si vous ne disposez pas du nom de votre locataire, découvrez de quelle manière consulter les détails de votre locataire.

  • Enter_the_Client_Secret_Here avec la valeur secrète de l’application cliente daemon que vous avez copiée précédemment.

  • Enter_the_Web_Api_Application_Id_Here avec l’ID de l’application (client) de l’API Web que vous avez copiée précédemment.

Notez que la propriété scopes dans la variable protectedResources est l’identificateur de ressource (URI d’ID d’application) de l’API web inscrite précédemment. L’URI d’étendue complète ressemble à api://Enter_the_Web_Api_Application_Id_Here/.default.

Obtenir un jeton d’accès

Dans votre éditeur de code, ouvrez le fichier auth.js, puis ajoutez le code suivant :

const msal = require('@azure/msal-node');
const { msalConfig, protectedResources } = require('./authConfig');
/**
 * With client credentials flows permissions need to be granted in the portal by a tenant administrator.
 * The scope is always in the format '<resource-appId-uri>/.default'. For more, visit:
 * https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
 */
const tokenRequest = {
    scopes: [`${protectedResources.apiToDoList.scopes}/.default`],
};

const apiConfig = {
    uri: protectedResources.apiToDoList.endpoint,
};

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

Dans le code :

  • Préparez l’objet tokenRequest et apiConfig. Le tokenRequest contient l’étendue pour laquelle vous demandez un jeton d’accès. L’étendue ressemble à api://Enter_the_Web_Api_Application_Id_Here/.default. L’objet apiConfig contient le point de terminaison de votre API web. En savoir plus concernant le flux d’informations d’identification du client OAuth 2.0.

  • Vous créez une instance de client confidentiel en passant l’objet msalConfig au constructeur de la classe ConfidentialClientApplication.

    const cca = new msal.ConfidentialClientApplication(msalConfig);
    
  • Utilisez ensuite la fonction acquireTokenByClientCredential pour obtenir un jeton d’accès. Vous implémentez cette logique dans la fonction getToken :

    cca.acquireTokenByClientCredential(tokenRequest);
    

Une fois un jeton d’accès obtenu, vous pouvez continuer à appeler une API.

Appeler une API

Dans votre éditeur de code, ouvrez le fichier fetch.js, puis ajoutez le code suivant :

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

Dans ce code, vous effectuez un appel à l’API web, en passant le jeton d’accès en tant que jeton de porteur dans l’en-tête de requête Authorization :

 Authorization: `Bearer ${accessToken}`

Vous utilisez le jeton d’accès que vous avez obtenu précédemment dans Obtenir un jeton d’accès.

Une fois l’API web reçu la demande, elle l’évalue, puis détermine s’il s’agit d’une demande d’application. Si le jeton d’accès est valide, l’API web renvoie les données requises. Sinon, l’API retourne une erreur HTTP 401 Unauthorized.

Finalisez votre application daemon

Depuis votre éditeur de code, ouvrez le fichier index.js, puis ajoutez le code suivant :

#!/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 'getToDos':
            try {
                const authResponse = await auth.getToken(auth.tokenRequest);
                const todos = await fetch.callApi(auth.apiConfig.uri, authResponse.accessToken);                
            } catch (error) {
                console.log(error);
            }

            break;
        default:
            console.log('Select an operation first');
            break;
    }
};

main();

Ce code constitue le point d’entrée de votre application. Vous utilisez la bibliothèque d’analyse d’argument de ligne de commande yargs JavaScript pour les applications Node.js afin d’extraire de manière interactive un jeton d’accès, puis appelez l’API. Vous utilisez les fonctions getToken et callApi définies précédemment :

const authResponse = await auth.getToken(auth.tokenRequest);
const todos = await fetch.callApi(auth.apiConfig.uri, authResponse.accessToken);                

Exécutez et testez l’application daemon ainsi que l’API

À ce stade, vous êtes prêt à tester votre application du client daemon et votre API web :

  1. Utilisez les étapes que vous avez apprises dans le tutoriel Sécuriser une API web ASP.NET pour démarrer votre API web. Votre API web est désormais prête à traiter les requêtes des clients. Si vous n’exécutez pas votre API web sur le port 44351 comme spécifié dans le fichier authConfig.js, vérifiez que vous mettez à jour le fichier authConfig.js pour utiliser le numéro de port correct d’API web.

  2. Dans votre terminal, vérifiez que vous êtes dans le dossier du projet contenant votre application Node.js daemon, par exemple ciam-call-api-node-daemon, puis exécutez la commande suivante :

    node . --op getToDos
    

Si votre application démon et votre API web s’exécutent correctement, vous devez trouver les données retournées par la variable de point de terminaison todos d’API web, comme dans le tableau JSON suivant, dans votre fenêtre de console :

{
    id: 1,
    owner: '3e8....-db63-43a2-a767-5d7db...',
    description: 'Pick up grocery'
},
{
    id: 2,
    owner: 'c3cc....-c4ec-4531-a197-cb919ed.....',
    description: 'Finish invoice report'
},
{
    id: 3,
    owner: 'a35e....-3b8a-4632-8c4f-ffb840d.....',
    description: 'Water plants'
}

Étape suivante