Поделиться через


Руководство: Вызов веб-API из вашего демон-приложения Node.js

В этом руководстве показано, как подготовить клиентское приложение Node.js управляющей программы с помощью потока предоставления учетных данных клиента Open Authorization (OAuth) 2.0, а затем настроить его для получения маркера доступа для вызова веб-API. Вы создадите приложение Node.js с помощью библиотеки проверки подлинности Майкрософт (MSAL) для узла, чтобы упростить добавление авторизации в приложение.

В этом руководстве:

  • Настройка ролей приложения для веб-API
  • Предоставление разрешений демон-приложению
  • Создайте приложение Node.js в Visual Studio Code, а затем установите зависимости.
  • Разрешите приложению Node.js получить токен доступа для вызова веб-API.

Предпосылки

  • Зарегистрируйте новое клиентское приложение в Центре администрирования Microsoft Entra, настроенное для учетных записей в любом каталоге организации и личных учетных записях Майкрософт. Дополнительные сведения см. в статье "Регистрация приложения ". Запишите следующие значения на странице обзора приложения для последующего использования:
    • Идентификатор приложения (клиента)
    • Идентификатор каталога (арендатора)
    • Доменное имя каталога (клиента) (например, contoso.onmicrosoft.com или contoso.com).
  • Добавьте секрет клиента в регистрацию клиентского приложения. Не используйте секреты клиента в рабочих приложениях. Вместо этого используйте сертификаты или федеративные учетные данные. Дополнительные сведения см. в статье о добавлении учетных данных в приложение.
  • Защищенный веб-API, который работает и готов принимать запросы. Убедитесь, что веб-API предоставляет следующие конечные точки через HTTPS:
    • GET /api/todolist, чтобы получить все задачи.
    • POST /api/todolist чтобы добавить TODO.
  • Node.js.
  • Хотя можно использовать любую интегрированную среду разработки (IDE), поддерживающую приложения React, в этом руководстве используется Visual Studio Code.

Настройка ролей приложения

API должно опубликовать как минимум одну роль приложения, также известную как разрешение приложения, чтобы клиентские приложения могли получить токен доступа от своего имени. Разрешения приложений — это тип разрешений, которые API должны публиковать, когда они хотят позволить клиентским приложениям успешно проходить проверку подлинности самостоятельно и без необходимости входа пользователей. Чтобы опубликовать разрешение приложения, выполните следующие действия.

  1. На странице Регистрация приложений выберите созданное приложение (например, ciam-ToDoList-api), чтобы открыть страницу обзора.

  2. В разделе "Управление" выберите роли приложения.

  3. Выберите " Создать роль приложения", а затем введите следующие значения, а затем нажмите кнопку "Применить ", чтобы сохранить изменения:

    Недвижимость Ценность
    Показать имя ToDoList.Прочитать.Все
    Допустимые типы членов Приложения
    Ценность ToDoList.Прочитать.Все
    Описание Разрешить приложению читать список ToDo каждого пользователя через TodoListApi.
    Вы хотите активировать эту роль приложения? Оставьте это отмеченным
  4. Снова нажмите кнопку "Создать роль приложения", а затем введите следующие значения для второй роли приложения, а затем нажмите кнопку "Применить ", чтобы сохранить изменения:

    Недвижимость Ценность
    Показать имя ToDoList.ЧитатьПисать.Все
    Допустимые типы членов Приложения
    Ценность ToDoList.ЧитатьПисать.Все
    Описание Разрешить приложению считывать и записывать список задач каждого пользователя с помощью ToDoListApi
    Вы хотите активировать эту роль приложения? Оставьте это отмеченным

Настройка запроса токена idtyp

Вы можете добавить необязательное утверждение idtyp, чтобы помочь веб-API определить, является ли токен токеном приложения или токеном приложения + пользователя . Хотя вы можете использовать сочетание утверждений scp и ролей для той же цели, использование утверждения idtyp — это самый простой способ различить токен приложения и токен приложения + пользователя. Например, значение этого утверждения — app, когда маркер предназначен только для приложений.

Предоставление разрешений API приложению управляющей программы

  1. На странице регистрации приложений выберите созданное приложение, например ciam-client-app.

  2. В разделе Управление выберите Разрешения API.

  3. В разделе Настроенные разрешения выберите Добавить разрешение.

  4. Выберите вкладку API, которые использует моя организация.

  5. В списке API выберите API, например ciam-ToDoList-api.

  6. Выберите параметр "Разрешения приложения". Мы выбираем этот параметр, так как приложение входит в систему самостоятельно, а не от имени пользователя.

  7. В списке разрешений выберите TodoList.Read.All, ToDoList.ReadWrite.All (при необходимости используйте поле поиска).

  8. Нажмите кнопку Add permissions (Добавить разрешения).

  9. На этом этапе вы правильно задали разрешения. Однако, так как приложение управляющей программы не позволяет пользователям взаимодействовать с ним, сами пользователи не могут согласиться на эти разрешения. Чтобы устранить эту проблему, администратор должен согласиться с этими разрешениями от имени всех пользователей в клиенте:

    1. Выберите "Предоставить согласие администратора" для <имени> клиента, а затем нажмите кнопку "Да".
    2. Выберите «Обновить», а затем убедитесь, что под < для обоих разрешений отображается Предоставлено для >имя вашего арендатора.

Создайте проект демона Node.js

Создайте папку для размещения приложения управляющей программы Node.js, например ciam-call-api-node-daemon:

  1. В терминале перейдите в каталог вашего приложения демона Node.js, например cd ciam-call-api-node-daemon, а затем запустите npm init -y. Эта команда создает файл package.json по умолчанию для проекта Node.js. Эта команда создает файл package.json по умолчанию для проекта Node.js.

  2. Создайте дополнительные папки и файлы для достижения следующей структуры проекта:

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

Установка зависимостей приложений

В терминале установите axios, yargs и пакеты @azure/msal-node, выполнив следующую команду:

npm install axios yargs @azure/msal-node   

Создание объекта конфигурации MSAL

В редакторе кода откройте файл authConfig.js, а затем добавьте следующий код:

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

Объект msalConfig содержит набор параметров конфигурации, используемых для настройки поведения потока авторизации.

В файле authConfig.js замените:

  • Enter_the_Application_Id_Here с идентификатором приложения (клиента) клиентского демон-приложения, зарегистрированного ранее.

  • Enter_the_Tenant_Subdomain_Here и замените его на поддомен каталога (домен клиента). Например, если основной домен клиента — это contoso.onmicrosoft.com, используйте contoso. Если у вас нет названия арендатора, узнайте, как посмотреть сведения об арендаторе.

  • Enter_the_Client_Secret_Here с значением секрета приложения управляющей программы клиента, скопированным ранее.

  • Enter_the_Web_Api_Application_Id_Here с идентификатором приложения (клиента) приложения веб-API, скопированного ранее.

Обратите внимание, что scopes свойство в protectedResources переменной — это идентификатор ресурса (URI идентификатора приложения) веб-API, зарегистрированного в рамках предварительных требований. Полный универсальный код ресурса (URI) области выглядит примерно так, как api://Enter_the_Web_Api_Application_Id_Here/.default.

Получение токена доступа

В редакторе кода откройте файл auth.js, а затем добавьте следующий код:

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

В коде:

  • Подготовьте объект tokenRequest и apiConfig. tokenRequest содержит область, для которой запрашивается маркер доступа. Область примерно такая: api://Enter_the_Web_Api_Application_Id_Here/.default. Объект apiConfig содержит конечную точку для вашего веб-API. Узнайте больше о потоке учетных данных клиента OAuth 2.0 .

  • Вы создаете конфиденциальный экземпляр клиента, передав объект msalConfig конструктору ConfidentialClientApplication класса.

    const cca = new msal.ConfidentialClientApplication(msalConfig);
    
  • Затем вы используете функцию acquireTokenByClientCredential для получения токена доступа. Эта логика реализуется в функции getToken:

    cca.acquireTokenByClientCredential(tokenRequest);
    

После получения токена доступа, можно вызвать API.

Вызов API

В редакторе кода откройте файл fetch.js, а затем добавьте следующий код:

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

В этом коде выполняется вызов к веб-API, передавая токен доступа в качестве токена типа Bearer в заголовке запроса Authorization.

 Authorization: `Bearer ${accessToken}`

Вы используете маркер доступа, который вы получили ранее в Получение маркера доступа.

После получения запроса веб-API он оценивает его, а затем определяет, что это запрос приложения. Если маркер доступа действителен, веб-API возвращает запрошенные данные. В противном случае API возвращает ошибку HTTP 401 Unauthorized.

Завершите приложение-демон

В редакторе кода откройте файл 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 '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();

Этот код является точкой входа в приложение. Вы используете JavaScript библиотеку синтаксического анализа аргументов командной строки yargs, чтобы интерактивно получать токен доступа для приложений Node.js, а затем вызывать API. Вы используете функции getToken и callApi, определенные ранее:

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

Запуск и тестирование приложения управляющей программы и API

На этом этапе вы готовы протестировать клиентское приложение управляющей программы и веб-API:

  1. Выполните действия, описанные в руководстве по безопасному ASP.NET веб-API, чтобы запустить веб-API . Ваш веб-API теперь готов обслуживать клиентские запросы. Если веб-API не запускается через порт 44351, как указано в файле authConfig.js, обязательно обновите файл authConfig.js, чтобы использовать правильный номер порта веб-API.

  2. В терминале убедитесь, что вы находитесь в папке проекта, содержащей приложение-демон Node.js, например ciam-call-api-node-daemon, а затем выполните следующую команду:

    node . --op getToDos
    

Если ваше демон-приложение и веб-API успешно выполняются, вы должны найти данные, возвращаемые конечной точкой веб-API переменной todos, аналогичной следующему массиву JSON, в окне консоли.

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

Следующий шаг