Partilhar via


Usar a autenticação OAuth com o Microsoft Dataverse

O OAuth 2.0 é o protocolo padrão do setor para autorização. Depois que os usuários do aplicativo fornecem credenciais para autenticar, o OAuth determina se eles estão autorizados a acessar os recursos.

Os aplicativos cliente devem dar suporte ao uso do OAuth para acessar dados usando a API Web. O OAuth permite autenticação de dois fatores (2FA) ou autenticação baseada em certificado para cenários de aplicativo servidor a servidor.

O OAuth requer um provedor de identidade para autenticação. Para o Dataverse, o provedor de identidade é o Microsoft Entra ID. Para autenticar usando uma conta corporativa ou de estudante da Microsoft, use a MSAL ( Biblioteca de Autenticação da Microsoft ).

Observação

Este artigo apresenta conceitos comuns relacionados à conexão ao Dataverse usando o OAuth com bibliotecas de autenticação. Esse conteúdo se concentra em como um desenvolvedor pode se conectar ao Dataverse, mas não no funcionamento interno do OAuth ou das bibliotecas. Para obter informações completas relacionadas à autenticação, consulte a documentação da ID do Microsoft Entra. O artigo O que é autenticação? É um bom lugar para começar.

Os exemplos que fornecemos são pré-configurados com valores de registro apropriados para que você possa executá-los sem gerar seu próprio registro de aplicativo. Ao publicar seus próprios aplicativos, você deve usar seus próprios valores de registro.

Registro de Aplicativo

Ao se conectar usando o OAuth, primeiro você deve registrar um aplicativo no cliente do Microsoft Entra ID. Como você deve registrar seu aplicativo depende do tipo de aplicativo que você deseja fazer.

Em todos os casos, comece com as etapas básicas para registrar um aplicativo descrito no artigo: Início Rápido: Registrar um aplicativo na plataforma de identidade da Microsoft. Para obter instruções específicas do Dataverse, consulte Passo a passo: registrar um aplicativo com a ID do Microsoft Entra.

As decisões que você precisa tomar nesta etapa dependem principalmente da opção Tipo de Aplicativo (consulte a próxima seção).

Tipos de registro de aplicativo

Quando você registra um aplicativo com a ID do Microsoft Entra, uma das decisões que você deve tomar é o tipo de aplicativo. Há dois tipos de aplicativos que você pode registrar:

Tipo de aplicativo Description
Aplicativo Web /API Cliente Web
Um tipo de aplicativo cliente que executa todo o código em um servidor Web.

Cliente baseado em agente de usuário
Um tipo de aplicativo cliente que baixa código de um servidor Web e é executado em um agente do usuário (por exemplo, um navegador da Web), como um SPA (Aplicativo de Página Única).
Native Um tipo de aplicativo cliente instalado nativamente em um dispositivo.

Quando você seleciona Web app /API, deve fornecer uma URL de 'Sign-On', que é a URL onde a Microsoft Entra ID envia a resposta de autenticação, incluindo um token se a autenticação tiver sido bem-sucedida. Enquanto você desenvolve um aplicativo, essa URL geralmente é definida para https://localhost/appname:[port] que você possa desenvolver e depurar seu aplicativo localmente. Ao publicar seu aplicativo, você precisa alterar esse valor para a URL publicada do aplicativo.

Ao selecionar Nativo, você deve fornecer um URI de Redirecionamento. Essa URL é um identificador exclusivo para o qual a ID do Microsoft Entra redirecionará o agente do usuário em uma solicitação OAuth 2.0. Essa URL normalmente é um valor formatado da seguinte forma: app://<guid>.

Dando acesso ao Dataverse

Se o seu aplicativo for um cliente que permite que o usuário autenticado realize operações, você deve configurar o aplicativo para ter a permissão delegada de acesso ao Dynamics 365 como usuários da organização.

Para obter etapas específicas para definir permissões, consulte Registrar um aplicativo com a ID do Microsoft Entra.

Se o aplicativo usar a autenticação S2S (Servidor para Servidor), essa etapa não será necessária. Essa configuração requer um usuário específico do sistema e as operações executadas por essa conta de usuário em vez de qualquer usuário que deve ser autenticado.

Usar Segredos de Cliente e Certificados

Para cenários de servidor para servidor, não há uma conta de usuário interativa para autenticação. Nesses casos, você precisa fornecer alguns meios para confirmar se o aplicativo é confiável. A confirmação é feita usando segredos ou certificados do cliente.

Para aplicativos registrados com o tipo de aplicativo Web/API, você pode configurar segredos. Esses segredos são definidos usando a área Chaves em Acesso à API nas Configurações do registro do aplicativo.

Para qualquer tipo de aplicativo, você pode carregar um certificado.

Mais informações: Conectar como um aplicativo

Usar bibliotecas de autenticação para se conectar

Use uma das bibliotecas de clientes de autenticação do Microsoft Entra ID com suporte da Microsoft para se conectar ao Dataverse, como a MSAL (Biblioteca de Autenticação da Microsoft). Essa biblioteca está disponível para várias plataformas, conforme descrito nos links fornecidos.

Observação

A ADAL (Biblioteca de Autenticação da Microsoft) não está mais recebendo atualizações ativamente e tem suporte apenas até junho de 2022. A MSAL é a biblioteca de autenticação recomendada a ser usada para projetos.

Para obter um exemplo de código que demonstra o uso de bibliotecas MSAL para autenticação com o Dataverse, consulte o exemplo de Início Rápido.

Bibliotecas de cliente .NET

O Dataverse dá suporte à autenticação de aplicativo com o endpoint da API Web pelo protocolo OAuth 2.0. Para suas aplicações .NET personalizadas, use MSAL para autenticação de aplicações com o endpoint da API Web.

O SDK do Dataverse para .NET inclui as classes de cliente CrmServiceClient e ServiceClient para lidar com a autenticação. A CrmServiceClient classe atualmente usa a ADAL para autenticação enquanto ServiceClient usa MSAL. Escrever o código do aplicativo para usar esses clientes remove a necessidade de gerenciar a autenticação diretamente. Ambos os clientes trabalham com os endpoints do SDK e da API Web.

Use o AccessToken com suas solicitações

O objetivo de usar as bibliotecas de autenticação é obter um token de acesso que você pode incluir com suas solicitações. Obter o token requer apenas algumas linhas de código e apenas mais algumas linhas para configurar um HttpClient para executar uma solicitação.

Importante

Conforme demonstrado no código de exemplo deste artigo, use o escopo "<environment-url>/user_impersonation" para um cliente público. Para um cliente confidencial, use um escopo de "<environment-url>/.default".

Exemplo simples

O exemplo a seguir é a quantidade mínima de código necessária para executar uma única solicitação de API Web, mas não é a abordagem recomendada. O código de exemplo usa a biblioteca MSAL e é extraído do exemplo de Início Rápido .

string resource = "https://contoso.api.crm.dynamics.com";
var clientId = "51f81489-12ee-4a9e-aaae-a2591f45987d";
var redirectUri = "http://localhost"; // Loopback for the interactive login.

// MSAL authentication
var authBuilder = PublicClientApplicationBuilder.Create(clientId)
    .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs)
    .WithRedirectUri(redirectUri)
    .Build();
var scope = resource + "/user_impersonation";
string[] scopes = { scope };

AuthenticationResult token =
    authBuilder.AcquireTokenInteractive(scopes).ExecuteAsync().Result;

// Set up the HTTP client
var client = new HttpClient
{
    BaseAddress = new Uri(resource + "/api/data/v9.2/"),
    Timeout = new TimeSpan(0, 2, 0)  // Standard two minute timeout.
};

HttpRequestHeaders headers = client.DefaultRequestHeaders;
headers.Authorization = new AuthenticationHeaderValue("Bearer", token.AccessToken);
headers.Add("OData-MaxVersion", "4.0");
headers.Add("OData-Version", "4.0");
headers.Accept.Add(
    new MediaTypeWithQualityHeaderValue("application/json"));

// Web API call
var response = client.GetAsync("WhoAmI").Result;

Essa abordagem simples não representa um bom padrão a ser seguido porque o token expira em cerca de uma hora. As bibliotecas MSAL armazenam em cache o token para você e o atualizam sempre que o AcquireTokenInteractive método é chamado. No entanto, neste exemplo simples, o token só é adquirido uma vez.

Exemplo demonstrando um manipulador de mensagens de delegação

A abordagem recomendada é implementar uma classe derivada deDelegatingHandler que será passada para o construtor do HttpClient. Esse manipulador permite substituir o método HttpClient.SendAsync para que o token de acesso seja atualizado pelas chamadas do método AcquireToken* com cada solicitação enviada pelo cliente HTTP.

O código a seguir é um exemplo de uma classe personalizada derivada de DelegatingHandler. Esse código é obtido do exemplo de Início Rápido Aprimorado que usa a biblioteca de autenticação MSAL.

class OAuthMessageHandler : DelegatingHandler
{
    private AuthenticationHeaderValue authHeader;
    public OAuthMessageHandler(string serviceUrl, string clientId, string redirectUrl, string username, string password,
            HttpMessageHandler innerHandler)
        : base(innerHandler)
    {
        string apiVersion = "9.2";
        string webApiUrl = $"{serviceUrl}/api/data/v{apiVersion}/";
        var authBuilder = PublicClientApplicationBuilder.Create(clientId)
                        .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs)
                        .WithRedirectUri(redirectUrl)
                        .Build();
        var scope = serviceUrl + "/user_impersonation";
        string[] scopes = { scope };
        // First try to get an authentication token from the cache using a hint.
        AuthenticationResult authBuilderResult=null;
        try
        {
            authBuilderResult = authBuilder.AcquireTokenSilent(scopes, username)
               .ExecuteAsync().Result;
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(
                $"Error acquiring auth token from cache:{System.Environment.NewLine}{ex}");
            // Token cache request failed, so request a new token.
            try
            {
                if (username != string.Empty && password != string.Empty)
                {
                    // Request a token based on username/password credentials.
                    authBuilderResult = authBuilder.AcquireTokenByUsernamePassword(scopes, username, password)
                                .ExecuteAsync().Result;
                }
                else
                {
                    // Prompt the user for credentials and get the token.
                    authBuilderResult = authBuilder.AcquireTokenInteractive(scopes)
                                .ExecuteAsync().Result;
                }
            }
            catch (Exception msalex)
            {
                System.Diagnostics.Debug.WriteLine(
                    $"Error acquiring auth token with user credentials:{System.Environment.NewLine}{msalex}");
                throw;
            }
        }
        //Note that an Microsoft Entra ID access token has finite lifetime, default expiration is 60 minutes.
        authHeader = new AuthenticationHeaderValue("Bearer", authBuilderResult.AccessToken);
    }

    protected override Task<HttpResponseMessage> SendAsync(
              HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        request.Headers.Authorization = authHeader;
        return base.SendAsync(request, cancellationToken);
    }
}

Ao usar essa OAuthMessageHandler classe, o método simples Main teria esta aparência.

class Program
{
    static void Main(string[] args)
    {
        try
        {
            //Get configuration data from App.config connectionStrings
            string connectionString = ConfigurationManager.ConnectionStrings["Connect"].ConnectionString;

            using (HttpClient client = SampleHelpers.GetHttpClient(connectionString, SampleHelpers.clientId,
                SampleHelpers.redirectUrl))
            {
                // Use the WhoAmI function
                var response = client.GetAsync("WhoAmI").Result;

                if (response.IsSuccessStatusCode)
                {
                    //Get the response content and parse it.
                    JObject body = JObject.Parse(response.Content.ReadAsStringAsync().Result);
                    Guid userId = (Guid)body["UserId"];
                    Console.WriteLine("Your UserId is {0}", userId);
                }
                else
                {
                    Console.WriteLine("The request failed with a status of '{0}'",
                                response.ReasonPhrase);
                }
                Console.WriteLine("Press any key to exit.");
                Console.ReadLine();
            }
        }
        catch (Exception ex)
        {
            SampleHelpers.DisplayException(ex);
            Console.WriteLine("Press any key to exit.");
            Console.ReadLine();
        }
    }
}

Leia as informações importantes a seguir sobre como usar uma cadeia de conexão ou autenticação de nome de usuário/senha no código do aplicativo.

Importante

A Microsoft recomenda usar o fluxo de autenticação mais seguro disponível. O fluxo de autenticação descrito neste artigo requer um alto grau de confiança no aplicativo e traz riscos que não estão presentes em outros fluxos. Você só deve usar esse fluxo quando outros fluxos mais seguros, como identidades gerenciadas, não forem viáveis.

Os valores de configuração foram movidos para uma string de conexão no arquivo App.config, e o cliente HTTP está configurado no método GetHttpClient.

public static HttpClient GetHttpClient(string connectionString, string clientId, string redirectUrl, string version = "v9.2")
{
    string url = GetParameterValueFromConnectionString(connectionString, "Url");
    string username = GetParameterValueFromConnectionString(connectionString, "Username");
    string password = GetParameterValueFromConnectionString(connectionString, "Password");
    try
    {
        HttpMessageHandler messageHandler = new OAuthMessageHandler(url, clientId, redirectUrl, username, password,
                        new HttpClientHandler());

        HttpClient httpClient = new HttpClient(messageHandler)
        {
            BaseAddress = new Uri(string.Format("{0}/api/data/{1}/", url, version)),

            Timeout = new TimeSpan(0, 2, 0)  //2 minutes
        };

        return httpClient;
    }
    catch (Exception)
    {
        throw;
    }
}

Consulte o exemplo de Início Rápido Aprimorado para obter o código completo.

Embora este exemplo use HttpClient.GetAsync em vez do substituído SendAsync, o mesmo fluxo de código se aplica a qualquer um dos HttpClient métodos que enviam uma solicitação.

Conectar-se como um aplicativo

Alguns aplicativos que você criará não se destinam a serem executados interativamente por um usuário. Por exemplo, talvez você queira criar um aplicativo cliente Web que possa executar operações em dados do Dataverse ou um aplicativo de console que execute algum tipo de tarefa agendada.

Embora você possa obter esses cenários usando credenciais para um usuário comum, essa conta de usuário precisaria usar uma licença paga. Essa abordagem não é recomendada.

Nesses casos, você pode criar um usuário de aplicativo especial associado a um aplicativo registrado do Microsoft Entra ID. Em seguida, use um segredo de chave configurado para o aplicativo ou carregue um certificado X.509 . Outro benefício dessa abordagem é que ela não consome uma licença paga.

Requisitos para se conectar como um aplicativo

Para se conectar como um aplicativo, você precisará:

  • Um aplicativo registrado
  • Um usuário do Dataverse associado ao aplicativo registrado
  • Conectar usando o segredo do aplicativo ou uma impressão digital do certificado

Registrar seu aplicativo

Ao registrar um aplicativo, você segue muitas das mesmas etapas descritas no Passo a passo: registrar um aplicativo com a ID do Microsoft Entra, com as seguintes exceções:

  • Você não precisa conceder a permissão Acessar o Dynamics 365 como usuários da organização.

    Esse aplicativo está associado a uma conta de usuário específica.

  • Você deve configurar um segredo para o registro do aplicativo ou carregar um certificado de chave pública.

Você pode criar ou exibir credenciais no registro do aplicativo em Gerenciar>Certificados & segredos.

Para adicionar um certificado (chave pública):

  1. Na guia Certificados , selecione Carregar certificado.
  2. Selecione o arquivo que você deseja carregar. Ele precisa ser um dos seguintes tipos de arquivo: .cer, .pem ou .crt.
  3. Forneça uma descrição.
  4. Selecione Adicionar.

Para adicionar um segredo do cliente (senha do aplicativo):

  1. Na guia Segredos do cliente , adicione uma descrição para o segredo do cliente.
  2. Selecione um período de expiração.
  3. Selecione Adicionar.

Importante

Depois de salvar as alterações de configuração, um valor secreto será exibido. Copie o valor do segredo para uso no código do aplicativo cliente, pois esse valor não estará acessível quando você sair da página.

Mais informações: Adicionar credenciais

Conta de usuário do Dataverse associada ao aplicativo registrado

A primeira coisa que você deve fazer é criar uma função de segurança personalizada que defina quais acessos e privilégios essa conta tem dentro da organização do Dataverse. Mais informações: Criar ou configurar uma função de segurança personalizada

Depois de criar a função de segurança personalizada, você deve criar a conta de usuário que a usará.

Criar manualmente um usuário de aplicativo do Dataverse

O procedimento para criar um usuário de aplicativo pode ser encontrado no artigo Administrar o Power Platform: Criar um usuário de aplicativo.

Depois de criar um usuário de aplicativo, associe o usuário do aplicativo à função de segurança personalizada que você criou.

Conectar-se usando o segredo do aplicativo

Se você estiver se conectando usando um segredo do cliente e usando o Microsoft.Xrm.Tooling.Connector.CrmServiceClient você pode usar um código semelhante, conforme mostrado aqui:

string SecretID = "00000000-0000-0000-0000-000000000000";
string AppID = "00001111-aaaa-2222-bbbb-3333cccc4444";
string InstanceUri = "https://yourorg.crm.dynamics.com";

string ConnectionStr = $@"AuthType=ClientSecret;
                        SkipDiscovery=true;url={InstanceUri};
                        Secret={SecretID};
                        ClientId={AppID};
                        RequireNewInstance=true";
using (ServiceClient svc = new ServiceClient(ConnectionStr))
{
    if (svc.IsReady)
    {
    //your code goes here
    }

}

Conectar-se usando uma impressão digital de certificado

Se você estiver se conectando usando um certificado e usando o Microsoft.Xrm.Tooling.Connector.CrmServiceClient você pode usar um código semelhante, conforme mostrado aqui:

string CertThumbPrintId = "DC6C689022C905EA5F812B51F1574ED10F256FF6";
string AppID = "00001111-aaaa-2222-bbbb-3333cccc4444";
string InstanceUri = "https://yourorg.crm.dynamics.com";

string ConnectionStr = $@"AuthType=Certificate;
                        SkipDiscovery=true;url={InstanceUri};
                        thumbprint={CertThumbPrintId};
                        ClientId={AppID};
                        RequireNewInstance=true";
using (ServiceClient svc = new ServiceClient(ConnectionStr))
{
    if (svc.IsReady)
    {
    //your code goes here
    }

}

Consulte também

Autenticação com os serviços Web do Microsoft Dataverse
Autenticando aplicativos do .NET Framework
Visão geral da Biblioteca de Autenticação da Microsoft