Dela via


Självstudie: Anropa ett webb-API från ditt Node.js daemon-program

Den här självstudien visar hur du förbereder din Node.js daemon-klientapp med hjälp av beviljandeflödet för open authorization (OAuth) 2.0-klientautentiseringsuppgifter och sedan konfigurerar den för att hämta en åtkomsttoken för att anropa ett webb-API. Du bygger ett Node.js-program med Microsoft Authentication Library (MSAL) för Node för att förenkla auktorisering i din app.

I den här handledningen;

  • Konfigurera app-roller för webbgränssnittet
  • Bevilja behörigheter till daemon-appen
  • Skapa en Node.js app i Visual Studio Code och installera sedan beroenden.
  • Aktivera Node.js-appen för att hämta en åtkomsttoken för att anropa ett webb-API.

Förutsättningar

  • Registrera en ny klientapp i administrationscentret för Microsoft Entra, konfigurerad för konton i alla organisationskataloger och personliga Microsoft-konton. Mer information finns i Registrera ett program . Registrera följande värden från programöversiktssidan för senare användning:
    • App-ID (klient-ID)
    • Katalog-ID (hyresgäst)
    • Katalogdomännamn (klientorganisation) (till exempel contoso.onmicrosoft.com eller contoso.com).
  • Lägg till en klienthemlighet i din klientappsregistrering. Använd inte klienthemligheter i produktionsappar. Använd certifikat eller federerade autentiseringsuppgifter i stället. Mer information finns i lägga till autentiseringsuppgifter i ditt program.
  • Ett skyddat webb-API som körs och är redo att ta emot begäranden. Kontrollera att webb-API:et exponerar följande slutpunkter via HTTPS:
    • GET /api/todolist för att få alla uppgifter.
    • POST /api/todolist för att lägga till en att-göra-post.
  • Node.js.
  • Även om vilken integrerad utvecklingsmiljö (IDE) som helst som stöder React-applikationer kan användas, använder den här handledningen Visual Studio Code.

Konfigurera app-roller

Ett API måste publicera minst en apputvecklarroll för applikationer, även kallat Programbehörighet, för att klientapparna ska få en åtkomsttoken i sin egen rätt. Programbehörigheter är den typ av behörigheter som API:er bör publicera när de vill att klientprogram ska kunna autentiseras som sig själva och inte behöver logga in användare. Följ dessa steg för att publicera en applikationsbehörighet:

  1. På sidan Appregistreringar väljer du det program som du skapade (till exempel ciam-ToDoList-api) för att öppna sidan Översikt.

  2. Under rubriken Hantera väljer du App-roller.

  3. Välj Skapa approlloch ange sedan följande värden och välj sedan Använd för att spara ändringarna:

    Fastighet Värde
    Visningsnamn ToDoList.Read.All
    Tillåtna medlemstyper Applikationer
    Värde ToDoList.Read.All
    Beskrivning Tillåt att appen läser alla användares ToDo-lista med hjälp av "TodoListApi"
    Vill du aktivera den här rollen för appen? Låt det vara ikryssat
  4. Välj Skapa approll igen och ange sedan följande värden för den andra approllen och välj sedan Använd för att spara ändringarna:

    Fastighet Värde
    Visningsnamn ToDoList.ReadWrite.All
    Tillåtna medlemstyper Applikationer
    Värde ToDoList.ReadWrite.All
    Beskrivning Tillåt att appen läser och skriver alla användares ToDo-lista med hjälp av "ToDoListApi"
    Vill du aktivera den här rollen för appen? Låt det vara ikryssat

Konfigurera idtyptokensanspråk

Du kan lägga till det valfria idtyp-anspråket för att hjälpa webb-API att avgöra om en token är en app-token eller en app-och-användar-token . Även om du kan använda en kombination av scp och rollanspråk för samma ändamål, är att använda idtyp-anspråket det enklaste sättet att skilja på en apptoken och en app + användartoken. Till exempel är värdet för detta anspråk app när token är en token endast för appar.

Bevilja API-behörigheter till daemonappen

  1. På sidan Appregistreringar väljer du det program som du skapade, till exempel ciam-client-app.

  2. Under Hantera väljer du API-behörigheter.

  3. Under Konfigurerade behörigheter väljer du Lägg till en behörighet.

  4. Välj fliken API:er som min organisation använder .

  5. I listan över API:er väljer du API:et, till exempel ciam-ToDoList-api.

  6. Välj alternativet Programbehörigheter . Vi väljer det här alternativet eftersom appen loggar in som sig själv, men inte för en användares räkning.

  7. I behörighetslistan väljer du TodoList.Read.All, ToDoList.ReadWrite.All (använd sökrutan om det behövs).

  8. Välj knappen Lägg till behörigheter.

  9. Nu har du tilldelat behörigheterna korrekt. Men eftersom daemon-appen inte tillåter användare att interagera med den, kan användarna själva inte samtycka till dessa behörigheter. För att lösa det här problemet måste du som administratör samtycka till dessa behörigheter för alla användare i klientorganisationen:

    1. Välj Bevilja administratörsmedgivande för <ditt klientnamn> och välj sedan Ja.
    2. Välj Uppdateraoch kontrollera sedan att Beviljas för <ditt klientnamn> visas under Status för båda behörigheterna.

Skapa daemonprojektet Node.js

Skapa en mapp som värd för ditt Node.js daemon-program, till exempel ciam-call-api-node-daemon:

  1. I terminalen ändrar du katalogen till din node daemon-appmapp, till exempel cd ciam-call-api-node-daemonoch kör sedan npm init -y. Det här kommandot skapar en standardfil för package.json för ditt Node.js projekt. Det här kommandot skapar en standardfil för package.json för ditt Node.js projekt.

  2. Skapa ytterligare mappar och filer för att uppnå följande projektstruktur:

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

Installera appens beroenden

Installera axios, yargs och @azure/msal-node paket i terminalen genom att köra följande kommando:

npm install axios yargs @azure/msal-node   

Skapa MSAL-konfigurationsobjekt

Öppna authConfig.js fil i kodredigeraren och lägg sedan till följande kod:

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

Objektet msalConfig innehåller en uppsättning konfigurationsalternativ som du använder för att anpassa auktoriseringsflödets beteende.

Ersätt i filen authConfig.js:

  • Enter_the_Application_Id_Here med program-ID:t (klient) för klientdaemonappen som du registrerade tidigare.

  • Enter_the_Tenant_Subdomain_Here och ersätt det med underdomänen Directory (tenant). Om din primära klientdomän till exempel är contoso.onmicrosoft.comanvänder du contoso. Om du inte har namnet på din hyresgäst, läs hur du kan hitta hyresgästens information.

  • Enter_the_Client_Secret_Here med klientdaemonappens hemliga värde som du kopierade tidigare.

  • Enter_the_Web_Api_Application_Id_Here med program-ID:t (klient) för webb-API-appen som du kopierade tidigare.

Observera att scopes egenskapen i variabeln protectedResources är resursidentifieraren (program-ID URI) för webb-API:et som du registrerade som en del av förhandskraven. Den fullständiga omfångs-URI:n ser ut ungefär som api://Enter_the_Web_Api_Application_Id_Here/.default.

Hämta en åtkomsttoken

Öppna auth.js fil i kodredigeraren och lägg sedan till följande kod:

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

I koden:

  • Förbered objektet tokenRequest och apiConfig. tokenRequest innehåller det omfång som du begär en åtkomsttoken för. Omfattningen ser ut ungefär som api://Enter_the_Web_Api_Application_Id_Here/.default. Objektet apiConfig innehåller slutpunkten till webb-API:et. Läs mer om OAuth 2.0-flöde för klientautentiseringsuppgifter.

  • Du skapar en konfidentiell klientinstans genom att skicka msalConfig-objektet till konstruktorn ConfidentialClientApplication klass.

    const cca = new msal.ConfidentialClientApplication(msalConfig);
    
  • Sedan använder du funktionen acquireTokenByClientCredential för att hämta en åtkomsttoken. Du implementerar den här logiken i funktionen getToken:

    cca.acquireTokenByClientCredential(tokenRequest);
    

När du har hämtat en åtkomsttoken kan du fortsätta att anropa ett API.

Anropa ett API

Öppna fetch.js fil i kodredigeraren och lägg sedan till följande kod:

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

I den här koden gör du ett anrop till webb-API:et genom att skicka åtkomsttoken som en bärartoken i begäran Authorization-huvudet:

 Authorization: `Bearer ${accessToken}`

Du använder åtkomsttoken som du hämtade tidigare i Hämta en åtkomsttoken.

När webb-API:et tar emot begäran utvärderas den och avgör sedan att det är en programbegäran. Om åtkomsttoken är giltig returnerar webb-API:et begärda data. Annars returnerar API:et ett 401 Unauthorized HTTP-fel.

Slutför din daemon-app

Öppna index.js fil i kodredigeraren och lägg sedan till följande kod:

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

Den här koden är startpunkten för din app. Du använder yargs JavaScript- kommandoradsargumentparsingbibliotek för Node.js appar för att interaktivt hämta en åtkomsttoken och sedan anropa API. Du använder funktionerna getToken och callApi som du definierade tidigare:

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

Köra och testa daemonapp och API

Nu är du redo att testa klientdaemonappen och webb-API:et:

  1. Använd de steg du lärde dig i handledningen Skydda en ASP.NET webb-API för att starta din webb-API. Webb-API:et är nu redo att hantera klientbegäranden. Om du inte kör webb-API:et på port 44351 enligt vad som anges i authConfig.js-filen kontrollerar du att du uppdaterar authConfig.js-filen för att använda rätt webb-API:s portnummer.

  2. I terminalen kontrollerar du att du är i projektmappen som innehåller din daemon-Node.js app, till exempel ciam-call-api-node-daemon, och kör sedan följande kommando:

    node . --op getToDos
    

Om daemonappen och webb-API:et körs korrekt bör du hitta de data som returneras av webb-API:ets slutpunkt todos variabel, ungefär som följande JSON-matris, i konsolfönstret:

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

Nästa steg