Autenticar um aplicativo EWS usando o OAuth

Aprenda a usar a autenticação OAuth com os aplicativos da API gerenciada do EWS.

Você pode usar o serviço de autenticação OAuth fornecido pelo Microsoft Entra para permitir que seus aplicativos de API Gerenciada do EWS acessem Exchange Online em Office 365. Para usar o OAuth com o aplicativo, você precisará:

  1. Registre seu aplicativo com Microsoft Entra.
  2. Adicione um código para obter um token de autenticação de um servidor de token.
  3. Adicione um token de autenticação a solicitações do EWS que você enviar.

Observação

A autenticação OAuth para o EWS só está disponível no Exchange Online como parte do Microsoft 365. Os aplicativos EWS que usam OAuth devem ser registrados com Microsoft Entra.

Para usar o código desse artigo, você precisará ter acesso ao seguinte:

Existem dois tipos de permissões OAuth que podem ser usadas para acessar as APIs do EWS no Exchange Online. Antes de prosseguir com o tutorial, você precisará escolher o tipo de permissão que deseja usar.

  • As permissões delegadas são usadas pelos aplicativos que têm um usuário conectado atualmente. Para esses aplicativos, o usuário ou um administrador concorda com as permissões que o aplicativo solicita e o aplicativo pode agir como o usuário conectado ao fazer chamadas API.
  • As permissões de aplicativo são usadas pelos aplicativos que são executados sem um usuário conectado. Por exemplo, aplicativos executados em segundo plano ou como daemons e podem acessar várias caixas de correio.

Registre seu aplicativo

Para usar o OAuth, um aplicativo deve ter uma ID do aplicativo emitida por Microsoft Entra. Neste tutorial, supõe-se que o aplicativo é um aplicativo de console, portanto, você precisa registrar seu aplicativo como um cliente público com Microsoft Entra. Você pode registrar um aplicativo no centro de administração do Microsoft Entra ou usando o Microsoft Graph.

  1. Abra um navegador e navegue até o centro de administração do Microsoft Entra e faça logon usando uma conta de trabalho ou de estudante.

  2. Selecione Identidade na navegação à esquerda e selecione Registros de aplicativo em Aplicativos.

  3. Selecione Novo registro. Na página Registrar um aplicativo, defina os valores da seguinte forma.

    • Defina Nome como um nome amigável para o seu aplicativo.
    • Defina tipos de conta com suporte como a opção que faz sentido para o seu cenário.
    • Para a URI de redirecionamento, altere a lista suspensa para cliente público (móvel e área de trabalho) e defina o valor para https://login.microsoftonline.com/common/oauth2/nativeclient.
  4. Escolha Registrar. Na página seguinte, copie os valores da ID do aplicativo (cliente) e da ID do diretório (locatário) e salve-os; você precisará deles mais tarde.

Observação

Os desenvolvedores podem fazer logon com uma conta corporativa ou escolar para registrar um aplicativo em um diretório de ID da Entra ou fazer logon com um MSA (conta pessoal) que é um convidado em um diretório da ID do Entra. Se os desenvolvedores não tiverem um diretório de ID do Entra, eles poderão obter um gratuitamente do Programa de Desenvolvedor M365.

Configurar para uma autenticação delegada

Se o aplicativo usar autenticação delegada, nenhuma configuração adicional será necessária. A plataforma de identidade para desenvolvedores da Microsoft permite aos aplicativos solicitar permissões de forma dinâmica, para que você não precise pré-configurar permissões no registro do aplicativo. No entanto, em alguns cenários (como o de em nome do fluxo) é necessário pré-configurar permissões. Use as etapas a seguir para pré-configurar as permissões EWS.

  1. Selecione Manifesto na navegação à esquerda em Gerenciar.

  2. Localize a propriedade requiredResourceAccess no manifesto e adicione o seguinte dentro dos colchetes ([]):

    {
        "resourceAppId": "00000002-0000-0ff1-ce00-000000000000",
        "resourceAccess": [
            {
                "id": "3b5f3d61-589b-4a3c-a359-5dd4b5ee5bd5",
                "type": "Scope"
            }
        ]
    }
    
  3. Selecione Salvar.

  4. Selecione Permissões de API em Gerenciar. Confirme se a permissão EWS.AccessAsUser.All está listada.

Configuração de autenticação somente para o aplicativo

Para usar as permissões do aplicativo, siga estas etapas adicionais.

  1. Selecione Manifesto na navegação à esquerda em Gerenciar.

  2. Localize a propriedade requiredResourceAccess no manifesto e adicione o seguinte dentro dos colchetes ([]):

    {
        "resourceAppId": "00000002-0000-0ff1-ce00-000000000000",
        "resourceAccess": [
            {
                "id": "dc890d15-9560-4a4c-9b7f-a736ec74ec40",
                "type": "Role"
            }
        ]
    }
    
  3. Selecione Salvar.

  4. Selecione Permissões de API em Gerenciar. Verifique se a permissão full_access_as_app está listada.

  5. Selecione Conceder consentimento de administrador para a organização e aceite o diálogo de consentimento.

  6. Selecione Certificados e segredos na navegação à esquerda em Gerenciar.

  7. Selecione Novo segredo do cliente, insira uma breve descrição e selecione Adicionar.

  8. Copie e salve o valor do segredo do cliente recém-adicionado, você precisará dele mais tarde.

Adicionar código para obter um token de autenticação

Os trechos de código a seguir mostram como usar a biblioteca de autenticação da Microsoft para obter tokens de autenticação para permissões delegadas e permissões de aplicativo. Esses trechos presumem que as informações necessárias para fazer a solicitação de autenticação sejam armazenadas no arquivo App.config do aplicativo. Esses exemplos não incluem a verificação de erros, confira o exemplos de códigos para o código completo.

Obter um token com autenticação delegada

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

Obter um token com autenticação somente para o aplicativo

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

Adicione um token de autenticação a solicitações do EWS.

Depois de receber o objetoAuthenticationResult, você pode usar a propriedade AcessToken para obter o token emitido pelo serviço de token.

// 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);

Para usar as permissões do aplicativo, você também precisará explicitamente representar uma caixa de correio que deseja acessar.

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

Exemplos de código

Autenticação delegada

A seguir, um exemplo de código completo que demonstra a realização de uma solicitação do EWS autenticada pelo OAuth usando autenticação delegada.

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

Autenticação somente para o aplicativo

A seguir, um exemplo de código completo que demonstra fazer uma solicitação do EWS autenticada pelo OAuth usando autenticação somente para o aplicativo.

Observação

Ao usar a representação, você sempre deve usar o cabeçalho de solicitação X-AnchorMailbox, que deve ser definido como o SMTP da caixa de correio representada.

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

O código de exemplo em ambos os casos exige um arquivo App.config com as seguintes entradas:

<?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>

Confira também