Usar la autenticación OAuth con Microsoft Dataverse

OAuth 2.0 es el protocolo estándar de la industria 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

Este tema introducirá los conceptos comunes relacionados con la conexión con Dataverse mediante OAuth con las bibliotecas de autenticación. Este contenido se centrará en la forma en que un programador puede conectarse a Dataverse pero no en el funcionamiento interno de OAuth ni en las bibliotecas. Si desea obtener más información sobre autencación, consulte la documentación de Microsoft Entra ID. ¿Qué es la autenticación? es un buen punto de inicio.

Los ejemplos que proporcionamos se preconfiguran con los valores apropiados de registro para que pueda ejecutarlos sin generar su propio registro de la aplicación. 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 consultar instrucciones específicas de Dataverse, consulte Tutorial: Registrar una aplicación con Microsoft Entra ID.

Las opciones que deberá tomar en este paso dependen principalmente de la opción de tipo de aplicación (véase a continuación).

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. Esta URL 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 se realizarán por la cuenta de ese usuario en lugar de cualquier usuario que tenga que ser autenticado.

Uso de Secretos y certificados del cliente

En los escenarios entre servidores, no aparecerá una cuenta de usuario interactiva para la autenticación. En estos casos, debe proporcionar algunos medios de confirmar que la aplicación es de confianza. Esto se realiza con secretos o certificados del cliente.

Para aplicaciones que se registran con el tipo de aplicación Aplicación web/API, puede configurar secretos. Estos se establecen utilizando el área Teclas de 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 Azure Active Directory (ADAL) ya no recibe actualizaciones de forma activa y está programada para recibir soporte solo 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 demuestra en el código de muestra de este artículo, utilice un ámbito "<environment-url>/user_impersonation" para un cliente público. Para un cliente confidencial, utilice un ámbito de "<environment-url>/.default".

Ejemplo sencillo:

A continuación se presenta la cantidad mínima de código necesaria para ejecutar una sola solicitud de web API, pero no es el método recomendado. Tenga en cuenta que este código utiliza la biblioteca MSAL y se toma del ejemplo QuickStart.

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 método sencillo no es un buen patrón que deba seguirse, porque el token expirará aproximadamente en una hora. Las bibliotecas de MSAL almacenarán en memoria caché el símbolo en su nombre y lo actualizarán cada vez que se llame al método AcquireTokenInteractive. 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 método recomendado consiste en implementar una clase derivada de DelegatingHandler, que se pasará al constructor del HttpClient. Este controlador le permite invalidar el método HttpClient.SendAsync para que el token de acceso se actualizará por las llamadas del método AcquireToken* con cada solicitud enviada por el cliente de Http.

A continuación se presenta un ejemplo de una clase personalizada derivada de DelegatingHandler. Este código utiliza la biblioteca MSAL y se toma del ejemplo QuickStart mejorado mencionado anteriormente.

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

Usando esta clase OAuthMessageHandler, el método sencillo Main se vería así.

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

Los valores de la cadena de configuración se han movido a una cadena de conexión de archivo App.config, y el cliente Http está configurado 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 este ejemplo use HttpClient.GetAsync en lugar del SendAsync reemplazado, solicitará todos los métodos de HttpClient que envían una solicitud.

Conectar como aplicación

Algunas aplicaciones que va a crear no están previstas para ser ejecutadas recíprocamente 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. Este no es el enfoque recomendado.

En estos casos puede crear un usuario de aplicación especial que está vinculado a una aplicación registrada de Microsoft Entra ID y usar la clave secreta configurada para la aplicación o cargar 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á:

  • 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 repite muchos de los pasos descritos en Tutorial: Registrar una aplicación con Microsoft Entra ID, con las excepciones siguientes:

  • No es necesario conceder el permiso Acceso a Dynamics 365 como usuarios de la organización.

    Esta aplicación estará 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.

Mientras registra la aplicación, seleccione la sección Claves en la página Configuración.

Para agregar un certificado:

  1. Seleccione Cargar clave pública.
  2. Seleccione el archivo que le gustaría cargar. Debe ser uno de los siguientes tipos de archivo: .cer, .pem, .crt.

Para agregar una contraseña:

  1. Agregue una descripción para la clave.
  2. Seleccionar una duración.
  3. Seleccione Guardar.

La columna situada más a la derecha incluirá el valor de clave, después de guardar los cambios de configuración. Asegúrese de copiar la clave para usarla en el código de aplicación cliente, ya que no se puede obtener acceso a ella una vez que sale de esta página.

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 definirá qué acceso y privilegios esta cuenta tendrá 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 lo usará.

Cree manualmente un usuario de la aplicación de Dataverse

El procedimiento para crear este usuario es diferente de crear un usuario con licencia. Lleve a cabo los pasos siguientes:

  1. Vaya a Configuración > Seguridad > Usuarios

  2. En la lista desplegable de vistas, seleccione Usuarios de la aplicación.

  3. Haga clic en Nuevo. A continuación compruebe que está usando el formulario Usuario de la aplicación.

    Si no ve los campos Identificador de la aplicación, URI del Id. la aplicación e Id. del objeto de Azure AD en el formulario, debe seleccionar el formulario Usuario de la aplicación de la lista:

    Seleccionar formulario de usuario de la aplicación.

  4. Agregue los valores correspondientes a los campos:

    Campo valor
    Nombre de usuario Un nombre para el usuario
    Id. de aplicación El valor del Id. de la aplicación para la aplicación registrada con Microsoft Entra ID.
    Nombre completo Nombre de la aplicación.
    Correo electrónico principal La dirección de correo electrónico del usuario.

    Los campos URI del Id. de la aplicación e Id. del objeto de Azure AD están bloqueados y no puede establecer los valores para estos campos.

    Cuando crea un este usuario los valores de estos campos se recuperarán de Microsoft Entra ID en función del valor de Identificador de la aplicación al guardar el usuario.

  5. Asocie el usuario de la aplicación con el rol de seguridad personalizado que creó.

Conectar con el secreto de la aplicación

Si se conecta mediante un secreto de cliente y el Microsoft.Xrm.Tooling.Connector.CrmServiceClient puede usar código como el siguiente:

string SecretID = "00000000-0000-0000-0000-000000000000";
string AppID = "545ce4df-95a6-4115-ac2f-e8e5546e79af";
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 está conectando mediante un certificado y el Microsoft.Xrm.Tooling.Connector.CrmServiceClient puede usar código como el siguiente:

string CertThumbPrintId = "DC6C689022C905EA5F812B51F1574ED10F256FF6";
string AppID = "545ce4df-95a6-4115-ac2f-e8e5546e79af";
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)

Nota

¿Puede indicarnos sus preferencias de idioma de documentación? Realice una breve encuesta. (tenga en cuenta que esta encuesta está en inglés)

La encuesta durará unos siete minutos. No se recopilan datos personales (declaración de privacidad).