Partager via


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

Ce tutoriel montre comment préparer votre application cliente de démon Node.js à l’aide du flux d’octroi d’informations d’identification du client OAuth (Open Authorization) 2.0, puis configurez-la pour acquérir un jeton d’accès pour appeler une API web. Vous allez créer une application Node.js à l’aide de la bibliothèque d’authentification Microsoft (MSAL) pour Node afin de simplifier l’ajout d’autorisation à votre application.

Dans ce tutoriel,

  • Configurer des rôles d’application pour l’API web
  • Accorder des autorisations à l’application démon
  • 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.

Conditions préalables

  • Inscrivez une nouvelle application cliente dans le Centre d’administration Microsoft Entra, configurée pour les comptes dans n’importe quel annuaire organisationnel et comptes Microsoft personnels. Pour plus d’informations, reportez-vous à l'enregistrement d'une application. Enregistrez les valeurs suivantes à partir de la page Vue d’ensemble de l’application pour une utilisation ultérieure :
    • ID d’application (client)
    • ID de l’annuaire (locataire)
    • Nom de domaine de répertoire (locataire) (par exemple, contoso.onmicrosoft.com ou contoso.com).
  • Ajoutez un secret client à l'inscription de votre application cliente. N’utilisez pas les secrets client dans les applications de production. Utilisez plutôt des certificats ou des informations d’identification fédérées. Pour plus d’informations, consultez ajouter des informations d’identification à votre application.
  • Une API web protégée en cours d’exécution et prête à accepter des requêtes. Vérifiez que votre API web expose les points de terminaison suivants via HTTPS :
    • GET /api/todolist pour obtenir tous les éléments todo.
    • POST /api/todolist pour ajouter un élément TODO.
  • Node.js.
  • Même s’il est possible d’utiliser n’importe quel environnement de développement intégré (IDE) prenant en charge les applications React, ce tutoriel utilise Visual Studio Code.

Configurer les rôles d’application

Une API doit publier au moins un rôle d'application pour les applications, également appelé autorisation d'application, pour que les applications clientes obtiennent un jeton d'accès en leur propre nom. Les autorisations d’application sont le type d’autorisations que les API doivent publier lorsqu’elles souhaitent permettre aux applications clientes de s’authentifier correctement en tant qu’elles-mêmes et qu’elles n’ont pas besoin de connecter des utilisateurs. Pour publier une autorisation d'application, procédez comme suit :

  1. Dans la page Inscriptions d’applications, sélectionnez l’application que vous avez créée (par exemple, ciam-ToDoList-api) pour ouvrir sa page Vue d’ensemble.

  2. Sous Gérer, sélectionnez Rôles d’applications.

  3. Sélectionnez Créer un rôle d'application, puis saisissez les valeurs suivantes, puis sélectionnez Appliquer pour enregistrer vos modifications :

    Propriété Valeur
    Nom complet ToDoList.Read.All
    Types de membres autorisés Applications
    Valeur ToDoList.Read.All
    Descriptif Autoriser l'application à lire la liste de tâches de chaque utilisateur à l'aide de 'TodoListApi'
    Voulez-vous activer le rôle de cette application ? Maintenez cette option cochée
  4. Sélectionnez à nouveau Créer un rôle d'application, puis saisissez les valeurs suivantes pour le deuxième rôle d'application, puis sélectionnez Appliquer pour enregistrer vos modifications :

    Propriété Valeur
    Nom complet ToDoList.ReadWrite.All
    Types de membres autorisés Applications
    Valeur ToDoList.ReadWrite.All
    Descriptif Autoriser l’application à lire et écrire la liste ToDo de chaque utilisateur à l’aide de « TodoListApi »
    Voulez-vous activer le rôle de cette application ? Maintenez cette option cochée

Configurer une revendication de jeton idtyp

Vous pouvez ajouter la revendication facultative idtyp pour aider l’API web à déterminer si un jeton est un jeton d’application ou une application + jeton utilisateur . Bien que vous puissiez utiliser une combinaison de revendications de scp et de rôles dans le même but, la revendication idtyp est le moyen le plus simple de distinguer un jeton d'application d'un jeton d'application + utilisateur. Par exemple, la valeur de cette revendication est app lorsque le jeton est un jeton d'application uniquement.

Accorder des autorisations d’API à l’application démon

  1. Dans la page Inscriptions d’applications, sélectionnez l’application que vous avez créée, par exemple, ciam-client-app.

  2. Sous Gérer, sélectionnez les autorisations d'API .

  3. Sous Autorisations configurées, sélectionnez Ajouter une autorisation.

  4. Sélectionnez l’onglet API utilisées par mon organisation.

  5. Dans la liste des API, sélectionnez l’API, par exemple ciam-ToDoList-api.

  6. Sélectionnez l’option Autorisations de l’application. Nous sélectionnons cette option, car l’application se connecte en tant que telle, mais pas au nom d’un utilisateur.

  7. Dans la liste des autorisations, sélectionnez TodoList.Read.All, ToDoList.ReadWrite.All (utilisez la zone de recherche si nécessaire).

  8. Sélectionnez le bouton Ajouter des autorisations.

  9. À ce stade, vous avez attribué les autorisations correctement. Toutefois, étant donné que l’application démon ne permet pas aux utilisateurs d’interagir avec elle, les utilisateurs eux-mêmes ne peuvent pas consentir à ces autorisations. Pour résoudre ce problème, en tant qu’administrateur, vous devez consentir à ces autorisations au nom de tous les utilisateurs du locataire :

    1. Sélectionnez Accorder le consentement administrateur pour <nom de votre locataire>, puis sélectionnez Oui.
    2. Sélectionnez Actualiser, puis vérifiez que Accordé pour le <nom de votre locataire> apparaît sous État pour les deux autorisations.

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 d’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 démon du client que vous avez inscrite précédemment.

  • Enter_the_Tenant_Subdomain_Here et remplacez-le par le sous-domaine du répertoire (locataire). Par exemple, si le domaine principal de votre 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 démon du client que vous avez copiée précédemment.

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

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

Acquérir 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 JavaScript yargs pour l'analyse d'arguments de ligne de commande des applications Node.js afin d'obtenir un jeton d'accès de manière interactive, puis d'appeler 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 didacticiel 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