Проверка подлинности приложения EWS с помощью OAuth

Узнайте, как использовать проверку подлинности OAuth для приложений на основе API, управляемого EWS.

Вы можете использовать службу проверки подлинности OAuth, предоставляемую Microsoft Entra, чтобы разрешить приложениям управляемого API EWS доступ к Exchange Online в Office 365. Чтобы использовать OAuth с приложением, необходимо выполнить следующие действия.

  1. Зарегистрируйте приложение с помощью Microsoft Entra.
  2. Добавление кода для получения токена проверки подлинности от сервера токенов.
  3. Добавление токена проверки подлинности в запросы EWS, которые вы отправляете.

Примечание.

Проверка подлинности OAuth для EWS доступна в Exchange Online только в составе Microsoft 365. Приложения EWS, использующие OAuth, должны быть зарегистрированы в Microsoft Entra.

Чтобы использовать код, приведенный в этой статье, необходимо иметь доступ к следующему:

Существует два типа разрешений OAuth, которые можно использовать для доступа к API, управляемому EWS, в Exchange Online. Перед тем как приступить к выполнению описанных в руководстве действий, нужно выбрать конкретный тип разрешения.

  • Делегированные разрешения используются в приложениях, предусматривающих вход пользователя. Для таких приложений пользователь или администратор соглашается предоставить разрешения, запрашиваемые приложением. Приложение при вызове API может действовать от имени выполнившего вход пользователя.
  • Разрешения приложений используются приложениями, не требующими от пользователя выполнения входа (например, фоновыми службами и управляющими программами, которые имеют доступ к нескольким почтовым ящикам).

Регистрация приложения

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

  1. Откройте браузер и перейдите к Центр администрирования Microsoft Entra и войдите с помощью рабочей или учебной учетной записи.

  2. Выберите Удостоверение в области навигации слева, а затем выберите Регистрация приложений в разделе Приложения.

  3. Выберите Новая регистрация. На странице Регистрация приложения задайте необходимые значения следующим образом.

    • Задайте понятное Название для своего приложения.
    • Настройте Поддерживаемые типы учетных записей, чтобы выбрать подходящий вариант.
    • В раскрывающемся списке URI перенаправления выберите Общедоступный клиент (мобильный и классический) и задайте для него значение https://login.microsoftonline.com/common/oauth2/nativeclient.
  4. Нажмите кнопку Зарегистрировать. На следующей странице скопируйте значение ИД приложения (клиента) и ИД каталога (клиента), и сохраните, это понадобится в дальнейшем.

Примечание.

Разработчики могут войти с помощью рабочей или учебной учетной записи, чтобы зарегистрировать приложение в каталоге Entra ID, или войти с помощью личная учетная запись (MSA), который является гостем в каталоге Entra ID. Если у разработчиков нет каталога Entra ID, они могут получить его бесплатно в программе разработчика M365.

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

Если приложение использует делегированную проверку подлинности, дополнительные настройки не требуются. Платформа удостоверений Майкрософт для разработчиков позволяет приложениям динамически запрашивать разрешения, поэтому вам не нужно предварительно настраивать разрешения на регистрацию приложений. Тем не менее в некоторых ситуациях (например, в потоке "от имени") требуются предварительно настроенные разрешения. Чтобы предварительно настроить разрешения EWS, выполните действия ниже.

  1. Нажмите Манифест в области навигации слева в разделе Управление.

  2. Найдите свойство requiredResourceAccess в манифесте и добавьте его в квадратные скобки ([]):

    {
        "resourceAppId": "00000002-0000-0ff1-ce00-000000000000",
        "resourceAccess": [
            {
                "id": "3b5f3d61-589b-4a3c-a359-5dd4b5ee5bd5",
                "type": "Scope"
            }
        ]
    }
    
  3. Нажмите Сохранить.

  4. Выберите Разрешения API в разделе Управление. Убедитесь в том, что разрешение EWS.AccessAsUser.All в списке.

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

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

  1. Нажмите Манифест в области навигации слева в разделе Управление.

  2. Найдите свойство requiredResourceAccess в манифесте и добавьте его в квадратные скобки ([]):

    {
        "resourceAppId": "00000002-0000-0ff1-ce00-000000000000",
        "resourceAccess": [
            {
                "id": "dc890d15-9560-4a4c-9b7f-a736ec74ec40",
                "type": "Role"
            }
        ]
    }
    
  3. Нажмите Сохранить.

  4. Выберите Разрешения API в разделе Управление. Убедитесь, что разрешение full_access_as_app в списке.

  5. Выберите Предоставить согласие администратора для организации и согласитесь с условиями.

  6. Нажмите Сертификаты и секреты в области навигации слева в разделе Управление.

  7. Выберите Новый секрет клиента, введите краткое описание и нажмите Добавить.

  8. Скопируйте Значение добавленного секрета клиента и сохраните его. оно потребуется позже.

Добавьте код для получения токена проверки подлинности

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

Получение токена с помощью делегированной проверки подлинности

// Using Microsoft.Identity.Client 4.22.0

// Configure the MSAL client to get tokens
var pcaOptions = new PublicClientApplicationOptions
{
    ClientId = ConfigurationManager.AppSettings["appId"],
    TenantId = ConfigurationManager.AppSettings["tenantId"]
};

var pca = PublicClientApplicationBuilder
    .CreateWithApplicationOptions(pcaOptions).Build();

// The permission scope required for EWS access
var ewsScopes = new string[] { "https://outlook.office365.com/EWS.AccessAsUser.All" };

// Make the interactive token request
var authResult = await pca.AcquireTokenInteractive(ewsScopes).ExecuteAsync();

Получение токена с помощью проверки подлинности только для приложений

// Using Microsoft.Identity.Client 4.22.0
var cca = ConfidentialClientApplicationBuilder
    .Create(ConfigurationManager.AppSettings["appId"])
    .WithClientSecret(ConfigurationManager.AppSettings["clientSecret"])
    .WithTenantId(ConfigurationManager.AppSettings["tenantId"])
    .Build();

// The permission scope required for EWS access
var ewsScopes = new string[] { "https://outlook.office365.com/.default" };

//Make the token request
var authResult = await cca.AcquireTokenForClient(ewsScopes).ExecuteAsync();

Добавление токена проверки подлинности в запросы EWS

После получения объекта AuthenticationResult можно использовать свойство AccessToken, чтобы получить токен, выданный службой токенов.

// Configure the ExchangeService with the access token
var ewsClient = new ExchangeService();
ewsClient.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
ewsClient.Credentials = new OAuthCredentials(authResult.AccessToken);

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

//Impersonate the mailbox you'd like to access.
ewsClient.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "test@demotenant.onmicrosoft.com");

Примеры кода

Делегированная проверка подлинности

Ниже приведен пример полного кода, в котором показано создание запроса EWS с проверкой подлинности OAuth при использовании делегированной проверки подлинности.

using Microsoft.Exchange.WebServices.Data;
using Microsoft.Identity.Client;
using System;
using System.Configuration;

namespace EwsOAuth
{
    class Program
    {
        static async System.Threading.Tasks.Task Main(string[] args)
        {
            // Using Microsoft.Identity.Client 4.22.0

            // Configure the MSAL client to get tokens
            var pcaOptions = new PublicClientApplicationOptions
            {
                ClientId = ConfigurationManager.AppSettings["appId"],
                TenantId = ConfigurationManager.AppSettings["tenantId"]
            };

            var pca = PublicClientApplicationBuilder
                .CreateWithApplicationOptions(pcaOptions).Build();

            // The permission scope required for EWS access
            var ewsScopes = new string[] { "https://outlook.office365.com/EWS.AccessAsUser.All" };

            try
            {
                // Make the interactive token request
                var authResult = await pca.AcquireTokenInteractive(ewsScopes).ExecuteAsync();

                // Configure the ExchangeService with the access token
                var ewsClient = new ExchangeService();
                ewsClient.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
                ewsClient.Credentials = new OAuthCredentials(authResult.AccessToken);

                // Make an EWS call
                var folders = ewsClient.FindFolders(WellKnownFolderName.MsgFolderRoot, new FolderView(10));
                foreach(var folder in folders)
                {
                    Console.WriteLine($"Folder: {folder.DisplayName}");
                }
            }
            catch (MsalException ex)
            {
                Console.WriteLine($"Error acquiring access token: {ex}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex}");
            }

            if (System.Diagnostics.Debugger.IsAttached)
            {
                Console.WriteLine("Hit any key to exit...");
                Console.ReadKey();
            }
        }
    }
}

Проверка подлинности только для приложений

Ниже приведен пример полного кода, в котором показано создание запроса EWS с проверкой подлинности OAuth при использовании проверки подлинности только для приложений.

Примечание.

При использовании олицетворения необходимо всегда использовать заголовок запроса X-AnchorMailbox, который должен быть установлен в протоколе SMTP-адреса олицетворенного почтового ящика.

using Microsoft.Exchange.WebServices.Data;
using Microsoft.Identity.Client;
using System;
using System.Configuration;

namespace EwsOAuth
{
    class Program
    {
        static async System.Threading.Tasks.Task Main(string[] args)
        {
            // Using Microsoft.Identity.Client 4.22.0
            var cca = ConfidentialClientApplicationBuilder
                .Create(ConfigurationManager.AppSettings["appId"])
                .WithClientSecret(ConfigurationManager.AppSettings["clientSecret"])
                .WithTenantId(ConfigurationManager.AppSettings["tenantId"])
                .Build();

            var ewsScopes = new string[] { "https://outlook.office365.com/.default" };

            try
            {
                var authResult = await cca.AcquireTokenForClient(ewsScopes)
                    .ExecuteAsync();

                // Configure the ExchangeService with the access token
                var ewsClient = new ExchangeService();
                ewsClient.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
                ewsClient.Credentials = new OAuthCredentials(authResult.AccessToken);
                ewsClient.ImpersonatedUserId =
                    new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "meganb@contoso.onmicrosoft.com");

                //Include x-anchormailbox header
                ewsClient.HttpHeaders.Add("X-AnchorMailbox", "meganb@contoso.onmicrosoft.com");

                // Make an EWS call
                var folders = ewsClient.FindFolders(WellKnownFolderName.MsgFolderRoot, new FolderView(10));
                foreach(var folder in folders)
                {
                    Console.WriteLine($"Folder: {folder.DisplayName}");
                }
            }
            catch (MsalException ex)
            {
                Console.WriteLine($"Error acquiring access token: {ex}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex}");
            }

            if (System.Diagnostics.Debugger.IsAttached)
            {
                Console.WriteLine("Hit any key to exit...");
                Console.ReadKey();
            }
        }
    }
}

В примере кода в обоих случаях требуется наличие файла App.config со следующими записями.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
  </startup>
  <appSettings>
    <!-- The application ID from your app registration -->
    <add key="appId" value="YOUR_APP_ID_HERE" />
    <!-- The tenant ID copied from your app registration -->
    <add key="tenantId" value="YOUR_TENANT_ID_HERE"/>
    <!-- The application's client secret from your app registration. Needed for application permission access -->
    <add key="clientSecret" value="YOUR_CLIENT_SECRET_HERE"/>
  </appSettings>
</configuration>

См. также