Compartir a través de


Usar autenticación de OAuth con Microsoft Dataverse

OAuth 2.0 es el protocolo estándar del sector para autorizaciones. Después de que los usuarios de aplicaciones proporcionan las credenciales para autenticarse, OAuth determina si están autorizadas para acceder a los recursos.

Las aplicaciones cliente deben admitir el uso de OAuth para el acceso a los datos mediante la API web. OAuth habilita la autenticación en dos fases (2FA) o autenticación basada en certificados para escenarios de aplicación entre servidores.

OAuth requiere un proveedor de identidad para la autenticación. Para Dataverse, el proveedor de identidades es Microsoft Entra ID. Para autenticarse usando una cuenta de trabajo o centro educativo de Microsoft, use Microsoft Authentication Libraries (MSAL).

Nota

En este artículo se presentan conceptos comunes relacionados con la conexión a Dataverse mediante OAuth con bibliotecas de autenticación. Este contenido se centra en cómo un desarrollador puede conectarse a Dataverse, pero no en el funcionamiento interno de OAuth o de las bibliotecas. Para obtener información completa relacionada con la autenticación, consulte la documentación de Microsoft Entra ID. El artículo ¿Qué es la autenticación? es un buen punto de partida.

Los ejemplos que se proporcionan están preconfigurados con los valores de registro adecuados para que pueda ejecutarlos sin generar su propio registro de aplicaciones. Al publicar sus propias aplicaciones, debe usar sus propios valores de registro.

Registro de aplicaciones

Al conectarse con OAuth, primero debe registrar una aplicación en su inquilino de Microsoft Entra ID. Cómo debe registrar la aplicación depende del tipo de aplicación que desee crear.

En todos los casos, comience con los pasos básicos para registrar una aplicación descrita en el artículo: Inicio rápido: Registrar una aplicación con la plataforma de identidad de Microsoft. Para obtener instrucciones específicas de Dataverse, consulte Tutorial: Registro de una aplicación con el identificador de Entra de Microsoft.

Las decisiones que debe tomar en este paso dependen principalmente de la opción Tipo de aplicación (consulte la sección siguiente).

Tipos de registro de la aplicación

Cuando registra una aplicación con Microsoft Entra ID, una de las decisiones que debe tomar es el tipo de aplicación. Hay dos tipos de aplicación que puede registrar:

Tipo de aplicación Descripción
Aplicación web/API Cliente web
Tipo de aplicación cliente que ejecuta todos los códigos en un servidor web.

Cliente basado en usuario-agente
Tipo de aplicación cliente que descarga código desde un servidor web y se ejecuta en un agente de usuario (por ejemplo, explorador web), como una aplicación de una sola página (SPA).
Modo nativo de Tipo de aplicación cliente que está instalada nativamente en un dispositivo.

Cuando selecciona Aplicación web/API debe proporcionar una Dirección URL de inicio de sesión que es la dirección URL a la que Microsoft Entra ID enviará la respuesta de autenticación, incluido un símbolo (token) si la autenticación se realiza correctamente. Mientras desarrolla una aplicación, esta URL se establece normalmente en https://localhost/appname:[port] por lo que puede desarrollar y depuración su aplicación localmente. Al publicar la aplicación, necesita cambiar este valor en la dirección URL publicada de la aplicación.

Cuando selecciona Nativo, debe proporcionar el identificador uniforme de recursos URI de una redirección. Este URL es un identificador único al que Microsoft Entra ID redirigirá el agente de usuario en una solicitud de OAuth 2.0. Esta URL suele ser un valor con un formato similar al siguiente: app://<guid>.

Dar acceso a Dataverse

Si su aplicación es un cliente que permite al usuario autenticado realizar operaciones, debe configurar la aplicación para que tenga Access Dynamics 365 como permiso delegado de los usuarios de la organización.

Para ver los pasos específicos para establecer permisos, consulte Registrar una aplicación con Microsoft Entra ID.

Si su aplicación va a usar la autenticación entre servidores (S2S), este paso no es obligatorio. Esa configuración requiere un usuario del sistema específico y las operaciones realizadas por esa cuenta de usuario en lugar de cualquier usuario que se deba autenticar.

Uso de Secretos y certificados del cliente

En escenarios de servidor a servidor, no hay una cuenta de usuario interactiva para autenticarse. En estos casos, debe proporcionar algunos medios de confirmar que la aplicación es de confianza. La confirmación se realiza mediante secretos de cliente o certificados.

Para aplicaciones que se registran con el tipo de aplicación Aplicación web/API, puede configurar secretos. Estos secretos se establecen mediante el área Claves en Acceso de API en Configuración para el registro de la aplicación.

Para ambos tipos de aplicación, puede cargar un certificado.

Más información: Conectar como aplicación

Uso de las bibliotecas de autenticación para conectar

Utilice una de las bibliotecas cliente de autenticación de Microsoft Entra ID compatibles con Microsoft para conectarse a Dataverse como la Biblioteca de autenticación de Microsoft (MSAL). Esta biblioteca está disponible para varias plataformas, como se muestra en los enlaces proporcionados.

Nota

La Biblioteca de autenticación de Microsoft (ADAL) ya no recibe actualizaciones activamente y solo se admite hasta junio de 2022. MSAL es la biblioteca de autenticación recomendada para usar en proyectos.

Para obtener una muestra de código que demuestra el uso de las bibliotecas MSAL para la autenticación con Dataverse, vea Ejemplo de inicio rápido.

Bibliotecas de cliente .NET

Dataverse admite la autenticación de aplicaciones con la API web punto de conexión mediante el protocolo OAuth 2.0. Para sus aplicaciones .NET personalizadas, use MSAL para la autenticación de aplicaciones con el punto de conexión API web.

SDK de Dataverse para .NET incluye clases de clientes CrmServiceClient yServiceClient para manejar la autenticación. La clase CrmServiceClient actualmente usa ADAL para la autenticación, mientras que ServiceClient utiliza MSAL. Escribir el código de su aplicación para usar estos clientes elimina la necesidad de administrar la autenticación directamente. Ambos clientes trabajan con los puntos de conexión SDK y Web API.

Use el AccessToken con sus solicitudes

El objetivo de usar las bibliotecas de autenticación es obtener un token de acceso que pueda incluir con las solicitudes. Obtener el token esto requiere solo unas líneas de código y solo unas cuantas líneas más para configurar un HttpClient para ejecutar una solicitud.

Importante

Como se muestra en el código de ejemplo de este artículo, use un ámbito «<environment-url>/user_impersonation» para un cliente público. Para un cliente confidencial, use un ámbito de «<environment-url>/.default».

Ejemplo sencillo:

El ejemplo siguiente es la cantidad mínima de código necesario para ejecutar una única solicitud de API web, pero no es el enfoque recomendado. El código de ejemplo usa la biblioteca MSAL y se toma del ejemplo de inicio 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;

Este enfoque sencillo no representa un buen patrón que se deba seguir porque el token expira en aproximadamente una hora. Las bibliotecas de MSAL almacenan en caché el token automáticamente y lo actualizan cada vez que se llama al AcquireTokenInteractive método . Sin embargo, en este ejemplo simple, el token solo se adquiere una vez.

Ejemplo que demuestra la delegación de un controlador de mensaje

El enfoque recomendado es implementar una clase derivada de DelegatingHandlerwillDelegatingHandler que se pasará al constructor de HttpClient. Este controlador permite invalidar el HttpClientmétodo .SendAsync para que el token de acceso se actualice mediante las AcquireToken* llamadas de método con cada solicitud enviada por el cliente Http.

El código siguiente es un ejemplo de una clase personalizada derivada de DelegatingHandler. Este código se toma del ejemplo de inicio rápido mejorado que usa la biblioteca de autenticación de 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);
    }
}

Al usar esta OAuthMessageHandler clase, el método simple Main tendría este aspecto.

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

Lea la siguiente información importante sobre el uso de una cadena de conexión o la autenticación de nombre de usuario/contraseña en el código de la aplicación.

Importante

Microsoft recomienda utilizar el flujo de autenticación más seguro disponible. El flujo de autenticación descrito en este artículo requiere un alto grado de confianza en la aplicación y conlleva riesgos que no están presentes en otros flujos. Solo debe usar este flujo cuando otros flujos más seguros, como las identidades administradas, no sean viables.

Los valores de cadena de configuración se transfieren a una cadena de conexión en el archivo App.config, y el cliente HTTP se configura en el 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;
    }
}

Ver el ejemplo Inicio rápido mejorado para el código completo.

Aunque en este ejemplo se usa HttpClient.GetAsync en lugar de invalidar SendAsync, el mismo flujo de código se aplica a cualquiera de los HttpClient métodos que envían una solicitud.

Conectar como aplicación

Algunas aplicaciones que va a crear no están diseñadas para ejecutarse interactivamente por un usuario. Por ejemplo, es posible que desee crear una aplicación cliente web que pueda realizar operaciones en datos de Dataverse, o una aplicación de consola que realice una tarea programada de algún tipo.

Aunque puede llegar a realizar estos escenarios usando las credenciales de un usuario normal, la cuenta de ese usuario necesitaría usar una licencia de pago. No se recomienda este enfoque.

En estos casos, puede crear un usuario de aplicación especial enlazado a una aplicación registrada de Microsoft Entra ID. A continuación, use un secreto de clave configurado para la aplicación o cargue un certificado X.509 . Otro ventaja de este método es que no consume una licencia de pago.

Requisitos para conectarse como aplicación

Para conectarse como una aplicación, necesitará lo siguiente:

  • Una aplicación registrada
  • Un usuario de Dataverse vinculado a la aplicación registrada
  • Conectarse usando la clave secreta de la aplicación o una huella digital del certificado

Registrar su aplicación

Al registrar una aplicación, sigue muchos de los mismos pasos descritos en Tutorial: Registrar una aplicación con el identificador de Entra de Microsoft, con las siguientes excepciones:

  • No es necesario otorgar el permiso Access Dynamics 365 como usuarios de la organización.

    Esta aplicación está enlazada a una cuenta de usuario específica.

  • Debe configurar un secreto para el registro de la aplicación O cargar un certificado de clave pública.

Puede crear o ver credenciales en el registro de su aplicación en Administrar>certificados y secretos.

Para agregar un certificado (clave pública):

  1. En la pestaña Certificados, seleccione Cargar certificado.
  2. Seleccione el archivo que le gustaría cargar. Debe ser uno de los siguientes tipos de archivo: .cer, .pem, .crt.
  3. Proporcione una descripción.
  4. Seleccione Agregar.

Para agregar un secreto de cliente (contraseña de aplicación):

  1. En la pestaña Secretos de cliente, agregue una descripción para su secreto de cliente.
  2. Seleccione un período de tiempo de vencimiento.
  3. Seleccione Agregar.

Importante

Después de guardar los cambios de configuración, se muestra un valor secreto. Asegúrese de copiar el valor del secreto para su uso en el código de la aplicación cliente, ya que ese valor no es accesible una vez que deje la página.

Más información: Agregar credenciales

Una cuenta de usuario de Dataverse vinculado a la aplicación registrada

Lo primero que debe hacer es crear un rol de seguridad personalizado que defina qué acceso y privilegios tiene esta cuenta dentro de la organización de Dataverse. Más información: Creación o configuración de un rol de seguridad personalizado

Después de crear el rol de seguridad personalizado, debe crear la cuenta de usuario que la usará.

Cree manualmente un usuario de la aplicación de Dataverse

El procedimiento para crear un usuario de la aplicación se puede encontrar en el artículo Administrar Power Platform: Crear un usuario de aplicación.

Tras crear un usuario de aplicación, asocie el usuario de la aplicación al rol de seguridad personalizado que ha creado.

Conectar con el secreto de la aplicación

Si se conecta mediante un secreto de cliente y usa Microsoft.Xrm.Tooling.ConnectorCrmServiceClient, puede usar un código similar al que se muestra aquí:

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 con una huella digital del certificado

Si se conecta mediante un certificado y usa el Microsoft.Xrm.Tooling.Connector.CrmServiceClient, usted puede utilizar un código similar al que se muestra aquí.

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
    }

}

Consultar también

Autenticación con servicios web Microsoft Dataverse
Autenticación de las aplicaciones de .NET Framework
Descripción general de la biblioteca de autenticación de Microsoft (MSAL)