Учебное пособие: Процесс аутентификации от службы приложений Azure через серверный API к Microsoft Graph

Узнайте, как создать и настроить серверное приложение службы приложений, чтобы принять учетные данные пользователя внешнего приложения, а затем обменять эти учетные данные для нижестоящей службы Azure. Этот подход позволяет пользователю войти в приложение службы приложений внешнего интерфейса, передать учетные данные в серверную службу приложений, а затем получить доступ к службе Azure с тем же удостоверением.

В этом руководстве вы узнаете, как:

  • Настройте бэкенд-приложение аутентификации для предоставления токена, предназначенного для последующей службы Azure.
  • Используйте код JavaScript для обмена маркером доступа пользователя, вошедшего в систему, на новый маркер для нижестоящей службы.
  • Используйте код JavaScript для доступа к нижестоящей службе.

Предпосылки

Выполните предыдущее руководство, чтобы получить доступ к Microsoft Graph из защищенного приложения JavaScript в качестве пользователя, прежде чем приступить к работе с этим руководством. Не удаляйте ресурсы в конце руководства. В этом руководстве предполагается, что у вас есть две службы приложений и соответствующие приложения проверки подлинности.

Предыдущее руководство использовало Azure Cloud Shell в качестве оболочки для Azure CLI. В этом учебном руководстве продолжается это использование.

Архитектура

В этом руководстве показано, как передать учетные данные пользователя, предоставленные интерфейсным приложением в серверное приложение, а затем в службу Azure. В этом руководстве нижестоящей службой является Microsoft Graph. Учетные данные пользователя используются для получения профиля из Microsoft Graph.

Архитектурный образ службы приложений, подключающийся к службе приложений, подключающейся к Microsoft Graph от имени пользователя, вошедшего в систему.

Процесс аутентификации пользователя для получения информации о Microsoft Graph в этой архитектуре:

В предыдущем руководстве описано:

  1. Войдите в клиентское приложение, настроенное для использования Active Directory в качестве поставщика удостоверений.
  2. Интерфейсная служба приложений передает маркер пользователя в серверную службу приложений.
  3. Серверное приложение защищено, чтобы клиентская часть могла выполнять запросы к API. Маркер доступа пользователя имеет аудиторию для внутреннего API и области user_impersonation.
  4. Регистрация серверного приложения уже имеет Microsoft Graph с указанной областью User.Read. Эта область добавляется по умолчанию ко всем регистрациям приложений.
  5. В конце предыдущего руководства поддельный профиль был возвращен в интерфейсное приложение, так как Graph не был подключен.

В этом руководстве расширена архитектура:

  1. Предоставьте администратору согласие на обход экрана согласия пользователя для внутреннего приложения.
  2. Измените код приложения, чтобы преобразовать маркер доступа, отправленный из внешнего приложения, в маркер доступа с необходимым разрешением для Microsoft Graph.
  3. Предоставьте код, чтобы серверное приложение обменивало токен на новый токен с областью применения нижестоящей службы Azure, такой как Microsoft Graph.
  4. Предоставьте код, чтобы серверное приложение использовало новый маркер для доступа к нижестоящей службе в качестве текущего пользователя, прошедшего проверку подлинности.
  5. Повторное развертывание серверного приложения с помощью az webapp up.
  6. В конце этого руководства реальный профиль возвращается в клиентское приложение, поскольку Graph подключен.

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

  • Измените интерфейсное приложение из предыдущего руководства.
  • Измените разрешение области внутреннего приложения проверки подлинности, так как User.Read по умолчанию добавляется ко всем приложениям проверки подлинности.

В предыдущем руководстве, когда пользователь входит в интерфейсное приложение, всплывающее окно запрашивает согласие пользователя.

В этом руководстве для чтения профиля пользователя из Microsoft Graph серверное приложение должно обменять маркер доступа вошедшего пользователя на новый маркер доступа с необходимыми разрешениями для Microsoft Graph. Так как пользователь не подключен непосредственно к внутреннему приложению, он не может получить доступ к экрану согласия в интерактивном режиме. Эту проблему необходимо решить, настроив регистрацию серверного приложения в Microsoft Entra ID, чтобы предоставить согласие администратора. Администратор Microsoft Entra обычно изменяет этот параметр.

  1. Откройте портал Azure и найдите ресурс для серверной службы приложений.

  2. Найдите раздел Параметры>Проверка подлинности.

  3. Выберите поставщика удостоверений, чтобы перейти к приложению проверки подлинности.

  4. В приложении проверки подлинности выберите "Управление разрешениями>API".

  5. Выберите "Предоставить согласие администратора" для каталога по умолчанию.

    Снимок экрана: приложение проверки подлинности портала Azure с выделенной кнопкой согласия администратора.

  6. Во всплывающем окне выберите "Да ", чтобы подтвердить согласие.

  7. Проверьте, что в столбце Статус указано "Предоставлено для каталога по умолчанию". С помощью этого параметра серверному приложению больше не нужно отображать экран согласия для вошедшего в систему пользователя и оно может напрямую запросить токен доступа. Пользователь, вошедший в систему, имеет доступ к настройкам области User.Read, потому что это область по умолчанию, в которой создается регистрация приложения.

    Снимок экрана приложения для аутентификации портала Azure с согласием администратора, отображаемым в столбце состояния.

2. Установка пакетов npm

В предыдущем руководстве серверное приложение не нуждалось в пакетах npm для проверки подлинности, так как только проверка подлинности была предоставлена путем настройки поставщика удостоверений на портале Azure. В этом руководстве маркер доступа пользователя, вошедшего в систему для внутреннего API, необходимо обменять на маркер доступа с Microsoft Graph в своей области. Этот обмен завершается двумя библиотеками, так как этот обмен больше не использует проверку подлинности службы приложений. Вместо этого он использует идентификатор Microsoft Entra и MSAL.js напрямую.

  1. Откройте Azure Cloud Shell и перейдите в серверное приложение каталога:

    cd js-e2e-web-app-easy-auth-app-to-app/backend
    
  2. Установите пакет npm библиотеки проверки подлинности Microsoft Azure (MSAL):

    npm install @azure/msal-node
    
  3. Установите пакет npm Microsoft Graph:

    npm install @microsoft/microsoft-graph-client
    

3. Добавьте код для обмена текущего токена на токен Microsoft Graph

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

  1. Откройте файл ./src/server.js.

  2. Раскомментируйте следующую зависимость в верхней части файла:

    import { getGraphProfile } from './with-graph/graph';
    
  3. В том же файле раскомментируйте graphProfile переменную:

    let graphProfile={};
    
  4. В том же файле раскомментируйте следующие строки в маршруте getGraphProfile, чтобы получить профиль из Microsoft Graph:

    // where did the profile come from
    profileFromGraph=true;
    
    // get the profile from Microsoft Graph
    graphProfile = await getGraphProfile(accessToken);
    
    // log the profile for debugging
    console.log(`profile: ${JSON.stringify(graphProfile)}`);
    
  5. Сохраните изменения: CTRL + s.

  6. Повторно разверните серверное приложение:

    az webapp up --resource-group myAuthResourceGroup --name <back-end-app-name> 
    
    

4. Проверьте код серверной части, чтобы обменять токен API серверной части на токен Microsoft Graph

Чтобы изменить токен аудитории API серверной части для токена Microsoft Graph, серверное приложение должно найти идентификатор клиента и использовать его в объекте конфигурации MSAL.js. Так как серверное приложение настроено корпорацией Майкрософт в качестве поставщика удостоверений, идентификатор клиента и несколько других обязательных значений уже находятся в параметрах приложения службы приложений.

Следующий код предоставляется в примере приложения. Вам нужно понять, почему она существует и как она работает, чтобы применить эту работу к другим приложениям, которые требуют такой же функциональности.

Проверка кода для получения идентификатора арендатора

  1. Откройте файл ./backend/src/with-graph/auth.js.

  2. Просмотрите функцию getTenantId() .

    export function getTenantId() {
    
        const openIdIssuer = process.env.WEBSITE_AUTH_OPENID_ISSUER;
        const backendAppTenantId = openIdIssuer.replace(/https:\/\/sts\.windows\.net\/(.{1,36})\/v2\.0/gm, '$1');
    
        return backendAppTenantId;
    }
    
  3. Эта функция получает текущий идентификатор клиента из переменной WEBSITE_AUTH_OPENID_ISSUER среды. Идентификатор извлекается из переменной с помощью регулярного выражения.

Проверка кода для получения маркера Graph с помощью MSAL.js

  1. В файле ./backend/src/with-graph/auth.js просмотрите функцию getGraphToken().

  2. Создайте объект конфигурации MSAL.js. Используйте конфигурацию MSAL для создания clientCredentialAuthority. Настройте запрос от имени другого лица. Затем используйте acquireTokenOnBehalfOf для обмена маркера доступа бэкенд API на маркер доступа Graph.

    // ./backend/src/auth.js
    // Exchange current bearerToken for Graph API token
    // Env vars were set by App Service
    export async function getGraphToken(backEndAccessToken) {
    
        const config = {
            // MSAL configuration
            auth: {
                // the backend's authentication CLIENT ID 
                clientId: process.env.WEBSITE_AUTH_CLIENT_ID,
                // the backend's authentication CLIENT SECRET 
                clientSecret: process.env.MICROSOFT_PROVIDER_AUTHENTICATION_SECRET,
                // OAuth 2.0 authorization endpoint (v2)
                // should be: https://login.microsoftonline.com/BACKEND-TENANT-ID
                authority: `https://login.microsoftonline.com/${getTenantId()}`
            },
            // used for debugging
            system: {
                loggerOptions: {
                    loggerCallback(loglevel, message, containsPii) {
                        console.log(message);
                    },
                    piiLoggingEnabled: true,
                    logLevel: MSAL.LogLevel.Verbose,
                }
            }
        };
    
        const clientCredentialAuthority = new MSAL.ConfidentialClientApplication(config);
    
        const oboRequest = {
            oboAssertion: backEndAccessToken,
            // this scope must already exist on the backend authentication app registration 
            // and visible in resources.azure.com backend app auth config
            scopes: ["https://graph.microsoft.com/.default"]
        }
    
        // This example has App Service validate token in runtime
        // from headers that can't be set externally
    
        // If you aren't using App Service's authentication, 
        // you must validate your access token yourself
        // before calling this code
        try {
            const { accessToken } = await clientCredentialAuthority.acquireTokenOnBehalfOf(oboRequest);
            return accessToken;
        } catch (error) {
            console.log(`getGraphToken:error.type = ${error.type}  ${error.message}`);
        }
    }
    

5. Проверьте внутренний код для доступа к Microsoft Graph с помощью нового токена

Чтобы получить доступ к Microsoft Graph от имени пользователя, вошедшего в интерфейсное приложение, изменения включают:

  • Настройка регистрации приложения Active Directory с разрешением API для нижестоящей службы Microsoft Graph с необходимой областью действия User.Read.
  • Предоставьте администратору согласие на обход экрана согласия пользователя для внутреннего приложения.
  • Измените код приложения, чтобы преобразовать маркер доступа, отправленный из внешнего приложения, в маркер доступа с необходимым разрешением для нижестоящей службы Microsoft Graph.

Теперь, когда код имеет правильный маркер для Microsoft Graph, используйте его для создания клиента в Microsoft Graph, а затем получите профиль пользователя.

  1. Откройте ./backend/src/graph.js

  2. В функции getGraphProfile(), получите токен, затем аутентифицированного клиента из токена, после чего получите профиль.

    // 
    import graph from "@microsoft/microsoft-graph-client";
    import { getGraphToken } from "./auth.js";
    
    // Create client from token with Graph API scope
    export function getAuthenticatedClient(accessToken) {
        const client = graph.Client.init({
            authProvider: (done) => {
                done(null, accessToken);
            }
        });
    
        return client;
    }
    export async function getGraphProfile(accessToken) {
        // exchange current backend token for token with 
        // graph api scope
        const graphToken = await getGraphToken(accessToken);
    
        // use graph token to get Graph client
        const graphClient = getAuthenticatedClient(graphToken);
    
        // get profile of user
        const profile = await graphClient
            .api('/me')
            .get();
    
        return profile;
    }
    

6. Проверка изменений

  1. Используйте интерфейсный веб-сайт в браузере. Возможно, потребуется обновить маркер, если срок его действия истек.

  2. Выберите Get user's profile. Это передает проверку подлинности в токен доступа на серверную часть.

  3. Серверная часть отвечает с реальным профилем Microsoft Graph для вашей учетной записи.

    Снимок экрана веб-браузера с интерфейсным приложением после успешного получения реального профиля из серверного приложения.

7. Очистка

На предыдущем шаге вы создали ресурсы Azure в группе ресурсов.

  1. Чтобы удалить группу ресурсов, выполните следующую команду в Cloud Shell. Эта команда может занять минуту на выполнение.

    az group delete --name myAuthResourceGroup
    
  2. Используйте идентификаторы клиентов, которые вы ранее нашли и записали в разделах Enable authentication and authorization для сервисных и пользовательских приложений.

  3. Удаление регистраций приложений для внешних и внутренних приложений.

    # delete app - do this for both front-end and back-end client ids
    az ad app delete --id <client-id>
    

Часто задаваемые вопросы

Я получил ошибку 80049217, что это означает?

Эта ошибка означает, CompactToken parsing failed with error code: 80049217что серверная служба приложений не авторизована для возврата маркера Microsoft Graph. Эта ошибка вызвана тем, что регистрация приложения не содержит User.Read разрешения.

Я получил ошибку AADSTS65001, что это означает?

Эта ошибка означает, AADSTS65001: The user or administrator has not consented to use the application with ID \<backend-authentication-id>. Send an interactive authorization request for this user and resourceчто серверное приложение проверки подлинности не настроено для согласия администратора. Так как ошибка отображается в журнале для внутреннего приложения, интерфейсное приложение не может сообщить пользователю, почему он не видел свой профиль в интерфейсном приложении.

Как подключиться к другой нижестоящей службе Azure в качестве пользователя?

В этом руководстве показано приложение API, прошедшее проверку подлинности в Microsoft Graph. Те же общие шаги можно применить для доступа к любой службе Azure от имени пользователя.

  1. Нет изменений в интерфейсном приложении. Только изменения, связанные с регистрацией приложения аутентификации серверной части и исходным кодом приложения серверной части.
  2. Обменяйте пользовательский токен, предназначенный для серверного API, на токен для нужной downstream-службы, к которой требуется получить доступ.
  3. Используйте токен в SDK дочерней службы для создания клиента.
  4. Используйте нижестоящего клиента для получения доступа к функционалу службы.