Настройка проверки подлинности стороннего поставщика удостоверений OAuth

Примечание.

Чтобы проверка подлинности работала для вкладки на мобильных клиентах, убедитесь, что используется клиентская библиотека JavaScript (TeamsJS) версии 1.4.1 или более поздней.

Приложению Microsoft Teams может потребоваться взаимодействие с различными службами, такими как Facebook, Twitter и Teams. Большинство из этих служб требуют проверки подлинности и авторизации для доступа. Teams сохраняет сведения о профиле пользователя в идентификаторе Microsoft Entra с помощью Microsoft Graph. В этой статье основное внимание уделяется использованию идентификатора Microsoft Entra для проверки подлинности для доступа к этой информации.

OAuth 2.0, открытый стандарт проверки подлинности, используется Microsoft Entra ID и многочисленными другими поставщиками услуг. Понимание OAuth 2.0 имеет важное значение при работе с проверкой подлинности в Teams и идентификатором Microsoft Entra. В приведенных примерах используется поток неявного предоставления OAuth 2.0, который получает сведения о профиле пользователя из идентификатора Microsoft Entra и Microsoft Graph.

Код, приведенный в этой статье, поступает из примера приложения Microsoft Teams Authentication Sample (Node). Он содержит статическую вкладку, которая запрашивает маркер доступа для Microsoft Graph и отображает основные сведения профиля текущего пользователя из Microsoft Entra идентификатора.

Общие сведения о потоке проверки подлинности для вкладок см . в разделе Поток проверки подлинности на вкладках.

Поток проверки подлинности на вкладках отличается от потока проверки подлинности в ботах.

Примечание.

В этом разделе представлена версия 2.0.x клиентской библиотеки JavaScript (TeamsJS) Microsoft Teams. Если вы используете более раннюю версию, ознакомьтесь с обзором библиотеки TeamsJS , чтобы узнать о различиях между последней версией TeamsJS и более ранними версиями.

Настройка приложения для использования идентификатора Microsoft Entra в качестве поставщика удостоверений

OAuth 2.0, поддерживающие поставщики удостоверений, не проверяют подлинность запросов от незарегистрированных приложений. Поэтому важно зарегистрировать приложения заранее. Чтобы зарегистрировать приложение с идентификатором Microsoft Entra, выполните следующие действия.

  1. Откройте портал регистрации приложений.

  2. Выберите приложение, чтобы просмотреть его свойства, или нажмите кнопку "Новая регистрация". Найдите раздел URI перенаправления для приложения.

  3. Выберите Интернет в раскрывающемся меню и обновите URL-адрес для конечной точки проверки подлинности. В примерах приложений TypeScript/Node.js и C#, доступных на GitHub, URL-адреса перенаправления следуют аналогичному шаблону:

    URL-адреса перенаправления: https://<hostname>/bot-auth/simple-start

Замените <hostname> фактическим узлом. Это может быть выделенный сайт размещения, например Azure, Glitch или туннель ngrok на локальный узел на компьютере разработки, например abcd1234.ngrok.io. Если у вас нет этих сведений, убедитесь, что вы завершили или размещали приложение (или пример приложения). Возобновите этот процесс, если у вас есть эти сведения.

Примечание.

Вы можете выбрать любого стороннего поставщика OAuth, например LinkedIn, Google и других. Процесс включения проверки подлинности для этих поставщиков аналогичен использованию идентификатора Microsoft Entra в качестве стороннего поставщика OAuth. Дополнительные сведения об использовании любого стороннего поставщика OAuth см. на веб-сайте конкретного поставщика.

Запуск потока проверки подлинности

Примечание.

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

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

Добавьте кнопку на страницу конфигурации или содержимого, чтобы пользователь при необходимости мог входить в систему. Это можно сделать на странице конфигурации вкладки или на любой странице содержимого.

Microsoft Entra идентификатор, как и большинство поставщиков удостоверений, не позволяет помещать содержимое в iframe. Это означает, что необходимо добавить всплывающую страницу для размещения поставщика удостоверений. В следующем примере эта страница имеет значение /tab-auth/simple-start. authentication.authenticate() Используйте функцию библиотеки TeamsJS, чтобы запустить эту страницу при нажатии кнопки.

import { authentication } from "@microsoft/teams-js";
authentication.authenticate({
    url: window.location.origin + "/tab/simple-start-v2",
    width: 600,
    height: 535})
.then((result) => {
    console.log("Login succeeded: " + result);
    let data = localStorage.getItem(result);
    localStorage.removeItem(result);
    let tokenResult = JSON.parse(data);
    showIdTokenAndClaims(tokenResult.idToken);
    getUserProfile(tokenResult.accessToken);
})
.catch((reason) => {
    console.log("Login failed: " + reason);
    handleAuthError(reason);
});

Примечания

  • Передаваемый URL-адрес authenticate() является начальной страницей потока проверки подлинности. В данном примере это /tab-auth/simple-start. Он должен соответствовать зарегистрированным на портале регистрации приложений Microsoft Entra.

  • Поток проверки подлинности должен начинаться на странице, которая находится в вашем домене. Этот домен также должен быть указан в validDomains разделе манифеста. Неисполнение приводит к пустому всплывающему оккупу.

  • Если не удается использовать authenticate(), всплывающее окно может не закрыться в конце процесса входа, что приведет к проблеме.

При показе всплывающей страницы (/tab-auth/simple-start) выполняется следующий код. Целью main страницы является перенаправление к поставщику удостоверений, чтобы пользователь смог войти в систему. Это перенаправление можно выполнить на стороне сервера с помощью HTTP 302, но в этом случае это выполняется на стороне клиента с помощью вызова window.location.assign(). Это также позволяет app.getContext() использовать для получения сведений, указывающих, которые могут быть переданы Microsoft Entra идентификатору.

app.getContext().then((context) => {
    // Generate random state string and store it, so we can verify it in the callback
    let state = _guid(); // _guid() is a helper function in the sample
    localStorage.setItem("simple.state", state);
    localStorage.removeItem("simple.error");

    // Go to the Azure AD authorization endpoint
    let queryParams = {
        client_id: "{{appId}}",
        response_type: "id_token token",
        response_mode: "fragment",
        scope: "https://graph.microsoft.com/User.Read openid",
        redirect_uri: window.location.origin + "/tab/simple-end",
        nonce: _guid(),
        state: state,
        // The context object is populated by Teams; the loginHint attribute
        // is used as hinting information
        login_hint: context.user.loginHint,
    };

    let authorizeEndpoint = `https://login.microsoftonline.com/${context.user.tenant.id}/oauth2/v2.0/authorize?${toQueryString(queryParams)}`;
    window.location.assign(authorizeEndpoint);
});

После завершения авторизации пользователь перенаправляется на страницу обратного вызова для вашего приложения, указанную в /tab-auth/simple-end.

Примечания

  • Подробнее о создании запросов и URL-адресов проверки подлинности см. в статье Получение сведений о контексте пользователя. Например, можно использовать имя входа пользователя в качестве login_hint значения для Microsoft Entra входа, что означает, что пользователю может потребоваться ввести меньше. Помните, что этот контекст не следует использовать непосредственно в качестве подтверждения личности, так как злоумышленник может загрузить вашу страницу в вредоносный браузер и предоставить ей любую нужную информацию.
  • Хотя контекст вкладки предоставляет полезные сведения о пользователе, не используйте эти сведения для проверки подлинности пользователя независимо от того, получаете ли они в качестве параметров URL-адреса содержимого вкладки или путем вызова app.getContext() функции в клиентской библиотеке JavaScript (TeamsJS) Microsoft Teams. Злоумышленник может вызвать URL-адрес содержимого вкладки с собственными параметрами, и веб-страница, мимикрирующая под Microsoft Teams, может загрузить URL-адрес содержимого вкладки в iframe и передать функции getContext() свои собственные данные. Сведения, связанные с удостоверениями, следует рассматривать в контексте вкладки просто как подсказки и проверять их перед использованием.
  • Параметр state используется для подтверждения того, что служба, вызывающая URI обратного вызова - именно та, которую вызывали вы. state Если параметр в обратном вызове не совпадает с параметром, отправленным во время вызова, обратный вызов не проверяется и должен быть завершен.
  • Необязательно включать домен поставщика удостоверений в validDomains список в файле manifest.json приложения.

Страница обратного вызова

В последнем разделе вы вызвали службу авторизации Microsoft Entra и передали сведения о пользователе и приложении, чтобы Microsoft Entra идентификатор мог предоставить пользователю собственный монолитный интерфейс авторизации. Ваше приложение не контролирует, что происходит в этом интерфейсе. Все, что он знает, это то, что возвращается, когда Microsoft Entra идентификатор вызывает указанную вами страницу обратного вызова (/tab-auth/simple-end).

На этой странице необходимо определить успех или сбой на основе сведений, возвращаемых идентификатором Microsoft Entra и вызовом authentication.notifySuccess() или authentication.notifyFailure(). Если вход выполнен успешно, у вас есть доступ к ресурсам службы.

// Split the key-value pairs passed from Azure AD
// getHashParameters is a helper function that parses the arguments sent
// to the callback URL by Azure AD after the authorization call
let hashParams = getHashParameters();
if (hashParams["error"]) {
    // Authentication/authorization failed
    localStorage.setItem("simple.error", JSON.stringify(hashParams));
} else if (hashParams["access_token"]) {
    // Get the stored state parameter and compare with incoming state
    let expectedState = localStorage.getItem("simple.state");
    if (expectedState !== hashParams["state"]) {
        // State does not match, report error
        localStorage.setItem("simple.error", JSON.stringify(hashParams));
        authentication.notifyFailure("StateDoesNotMatch");
    } else {
        // Success -- return token information to the parent page.
        // Use localStorage to avoid passing the token via notifySuccess; instead we send the item key.
        let key = "simple.result";
        localStorage.setItem(key, JSON.stringify({
            idToken: hashParams["id_token"],
            accessToken: hashParams["access_token"],
            tokenType: hashParams["token_type"],
            expiresIn: hashParams["expires_in"]
        }));
        authentication.notifySuccess(key);
    }
} else {
    // Unexpected condition: hash does not contain error or access_token parameter
    localStorage.setItem("simple.error", JSON.stringify(hashParams));
    authentication.notifyFailure("UnexpectedFailure");
}

Этот код анализирует пары "ключ-значение", полученные от идентификатора Microsoft Entra в, window.location.hash с помощью вспомогательной getHashParameters() функции. Если найден access_token и значение state совпадает со значением, указанным в начале потока проверки подлинности, возвращается маркер доступа на вкладку путем вызова notifySuccess(); в противном случае генерируется сообщение об ошибке с помощью notifyFailure().

Примечания

Сообщение NotifyFailure() имеет следующие предопределенные причины:

  • CancelledByUser: пользователь закрыл всплывающее окно до завершения потока проверки подлинности.

    Примечание.

    Мы не рекомендуем использовать same-origin значения или same-origin-allow-popups для Cross-Origin-Opener-Policy заголовка ответа на страницах входа, так как это нарушает подключение к родительскому окну и приводит к преждевременному возврату вызова API проверки подлинности с ошибкой CancelledByUser .

  • FailedToOpenWindow не удалось открыть всплывающее окно. При запуске Microsoft Teams в браузере эта ошибка указывает на то, что окно было заблокировано блокировщиком всплывающих окон браузера.

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

Приложение может задать собственный файл cookie сеанса, чтобы пользователю не нужно было заново входить в систему при возврате на вкладку на текущем устройстве.

Примечание.

  • Chrome 80, запланированный на выпуск в начале 2020 г., вводит новые значения файлов cookie и по умолчанию реализует политики файлов cookie. Рекомендуем задать использование файлов cookie в явном виде, а не полагаться на поведение браузера по умолчанию. См. разделАтрибут файла cookie SameSite (обновление 2020 г.).
  • Чтобы получить соответствующий маркер для бесплатных и гостевых пользователей Microsoft Teams, убедитесь, что приложения используют конечную точку https://login.microsoftonline.com/**{tenantId}**для конкретного клиента. Идентификатор клиента можно получить из сообщения бота или контекста вкладки. Если приложения используют https://login.microsoftonline.com/common, пользователи могут получать неправильные маркеры, в результате чего они будут входить в "домашний" клиент, а не в тот клиент, в который они вошли.

Дополнительные сведения о едином входе см. в статье Автоматическая проверка подлинности.

Пример кода

Пример кода, показывающий процесс проверки подлинности вкладки с использованием идентификатора Microsoft Entra:

Название примера Описание .NET Node.js Манифест
Единый вход на вкладке В этом примере приложения показан Microsoft Entra единого входа для вкладок в Teams. Просмотр View,
Teams Toolkit
Н/Д
Единый вход в tab, bot и message extension (ME) В этом примере показан единый вход для tab, bot и ME— поиск, действие, распутывание ссылок. Просмотр Просмотр Просмотр

Дополнительные ресурсы