Desafíos de notificaciones, solicitudes de notificaciones y funcionalidades de cliente

Un desafío de notificaciones es una respuesta enviada desde una API que indica que un token de acceso enviado por una aplicación cliente no tiene notificaciones suficientes. Esto puede deberse a que el token no satisface las directivas de acceso condicional establecidas para esa API o se ha revocado el token de acceso.

La aplicación cliente realiza una solicitud de notificaciones para redirigir al usuario de nuevo al proveedor de identidades para recuperar un nuevo token con notificaciones que cumplan los demás requisitos que no se han cumplido.

Las aplicaciones que usan características de seguridad mejoradas, como Evaluación continua de acceso (CAE) y el contexto de autenticación de acceso condicional, deben estar preparadas para controlar los desafíos de las notificaciones.

La aplicación recibe desafíos de notificaciones de servicios populares como Microsoft Graph solo si declara sus funcionalidades de cliente en sus llamadas al servicio.

Formato de encabezado de desafío de notificaciones

El desafío de notificaciones es una directiva como un encabezado www-authenticate devuelto por una API cuando un token de acceso que se le presenta no está autorizado y, en su lugar, se requiere un nuevo token de acceso con las funcionalidades correctas. El desafío de notificaciones consta de varias partes: el código de estado HTTP de la respuesta y el encabezado www-authenticate, que a su vez tiene varias partes y debe contener una directiva de notificaciones.

Este es un ejemplo:

HTTP 401; Unauthorized

www-authenticate =Bearer realm="", authorization_uri="https://login.microsoftonline.com/common/oauth2/authorize", error="insufficient_claims", claims="eyJhY2Nlc3NfdG9rZW4iOnsiYWNycyI6eyJlc3NlbnRpYWwiOnRydWUsInZhbHVlIjoiY3AxIn19fQ=="

Código de estado HTTP: debe ser 401 No autorizado.

Encabezado de respuesta www-authenticate que contiene:

Parámetro Obligatorio/opcional Descripción
Tipo de autenticación Obligatorio Debe ser Portador.
Dominio Opcional Identificador de inquilino o nombre de dominio de inquilino (por ejemplo, microsoft.com) al que se accede. DEBE ser una cadena vacía en el caso de que la autenticación pase por el punto de conexión común.
authorization_uri Obligatorio URI del punto de conexión de authorize donde se puede realizar una autenticación interactiva si es necesario. Si se especifica en el dominio, la información del inquilino DEBE incluirse en authorization_uri. Si el dominio es una cadena vacía, authorization_uri DEBE estar en el punto de conexión común.
error Obligatorio Tiene que ser "insufficient_claims" cuando se deba generar un desafío de notificaciones.
claims Se requiere cuando el error es "insufficient_claims". Cadena entre comillas que contiene una solicitud de notificaciones codificada en base 64. La solicitud de notificaciones debe solicitarlas para "access_token" en el nivel superior del objeto JSON. El valor (notificaciones solicitadas) dependerá del contexto y se especificará más adelante en este documento. Por motivos de tamaño, las aplicaciones de usuario de confianza DEBEN minificar el objeto JSON antes de la codificación en base 64. El JSON sin formato del ejemplo anterior es {"access_token":{"acrs":{"essential":true,"value":"cp1"}}}.

La respuesta 401 puede contener más de un encabezado www-authenticate. Todos los campos de la tabla anterior deben estar incluidos en el mismo encabezado www-authenticate. El encabezado www-authenticate que contiene el desafío de notificaciones puede contener otros campos. Los campos del encabezado están desordenados. Según RFC 7235, cada nombre de parámetro debe aparecer solo una vez por cada desafío del esquema de autenticación.

Solicitud de notificaciones

Cuando una aplicación recibe un desafío de notificaciones, significa que el token de acceso anterior ya no se considera válido. En este escenario, la aplicación debe borrar el token de cualquier caché local o sesión de usuario. A continuación, debe redirigir el usuario que ha iniciado sesión a Microsoft Entra ID para recuperar un nuevo token mediante el flujo de código de autorización de OAuth 2.0 con un parámetro notificaciones que cumplirá los demás requisitos que no se han cumplido.

Este es un ejemplo:

GET https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/oauth2/v2.0/authorize
?client_id=00001111-aaaa-2222-bbbb-3333cccc4444
&redirect_uri=https%3A%2F%contoso.com%3A44321%2Fsignin-oidc
&response_type=code
&scope=openid%20profile%20offline_access%20user.read%20Sites.Read.All
&response_mode=form_post
&login_hint=kalyan%ccontoso.onmicrosoft.com
&domain_hint=organizations
&claims=%7B%22access_token%22%3A%7B%22acrs%22%3A%7B%22essential%22%3Atrue%2C%22value%22%3A%22c1%22%7D%7D%7D

El desafío de notificaciones debe pasarse como parte de todas las llamadas a un punto de conexión de Microsoft Entra /autorizar hasta que se recupere correctamente un token. Una vez recuperado el token, ya no es necesario.

Para rellenar el parámetro de notificaciones, el desarrollador tiene que:

  1. Descodificar la cadena en base 64 recibida anteriormente.
  2. Codificar la cadena y volver a agregarla al parámetro claims.

Tras la finalización de este flujo, la aplicación recibe un token de acceso que tiene las demás notificaciones que demuestran que el usuario cumple las condiciones necesarias.

Capacidades de cliente

Las funcionalidades de cliente ayudan a los proveedores de recursos, como una API web, a detectar si la aplicación cliente que realiza la llamada entiende el desafío de notificaciones y puede, a continuación, personalizar su respuesta en consecuencia. Esta funcionalidad puede ser útil cuando no todos los clientes de API son capaces de controlar los desafíos de notificaciones y algunas versiones anteriores todavía esperan una respuesta diferente.

Algunas aplicaciones populares, como Microsoft Graph, envían desafíos de notificaciones solo si la aplicación cliente que realiza la llamada declara que es capaz de controlarlos mediante las funcionalidades de cliente.

Para evitar tráfico adicional o impactos en la experiencia del usuario, Microsoft Entra ID no supone que la aplicación pueda controlar las notificaciones impugnadas a menos que opte explícitamente por participar. Una aplicación no recibirá desafíos de notificaciones (y no podrá usar las características relacionadas, como tokens CAE), a menos que declare que está listo para controlarlos con la funcionalidad "cp1".

Cómo comunicar las funcionalidades de cliente a Microsoft Entra ID

El parámetro de notificaciones del ejemplo siguiente muestra cómo una aplicación cliente comunica su funcionalidad a Microsoft Entra ID en un flujo de código de autorización de OAuth 2.0.

Claims: {"access_token":{"xms_cc":{"values":["cp1"]}}}

Use el código siguiente si usa la biblioteca MSAL:

_clientApp = PublicClientApplicationBuilder.Create(App.ClientId)
 .WithDefaultRedirectUri()
 .WithAuthority(authority)
 .WithClientCapabilities(new [] {"cp1"})
 .Build();

Los que usan Microsoft.Identity.Web pueden agregar el código siguiente al archivo de configuración:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "ClientId": 'Enter_the_Application_Id_Here' 
    "ClientCapabilities": [ "cp1" ],
    // remaining settings...
},

Consulte el fragmento de código siguiente para ver una solicitud de ejemplo a Microsoft Entra ID:

GET https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/oauth2/v2.0/authorize
?client_id=00001111-aaaa-2222-bbbb-3333cccc4444
&redirect_uri=https%3A%2F%contoso.com%3A44321%2Fsignin-oidc
&response_type=code
&scope=openid%20profile%20offline_access%20user.read%20Sites.Read.All
&response_mode=form_post
&login_hint=kalyan%ccontoso.onmicrosoft.com
&domain_hint=organizations
&claims=%7B%22access_token%22%3A%7B%22xms_cc%22%3A%7B%22values%22%3A%5B%22cp1%22%5D%7D%7D%7D

Cuando ya tenga una carga existente para el parámetro de notificaciones, puede agregar esto al conjunto existente.

Por ejemplo, si ya tiene la siguiente respuesta de una operación de contexto de autenticación de acceso a condiciones;

{"access_token":{"acrs":{"essential":true,"value":"c25"}}}

va a anteponer la funcionalidad del cliente en la carga de notificaciones existente.

{"access_token":{"xms_cc":{"values":["cp1"]},"acrs":{"essential":true,"value":"c25"}}}

Recepción de la notificación xms_cc en un token de acceso

Para recibir información sobre si las aplicaciones cliente pueden controlar los desafíos de notificaciones, un implementador de API debe solicitar xms_cc como una notificación opcional en su manifiesto de aplicación.

La notificación xms_cc con un valor de "cp1" en el token de acceso es la manera autoritativa de identificar que una aplicación cliente es capaz de controlar un desafío de notificaciones. xms_cc es una notificación opcional que no siempre se emitirá en el token de acceso, incluso si el cliente envía una solicitud de notificaciones con "xms_cc". Para que un token de acceso contenga la notificación xms_cc, la aplicación de recursos (es decir, el implementador de API) debe solicitar xms_cc como una notificación opcional en su manifiesto de aplicación. Cuando se solicita como notificación opcional, xms_cc se agrega al token de acceso solo si la aplicación cliente envía xms_cc en la solicitud de notificaciones. El valor de la solicitud de notificación de xms_cc se incluye como el valor de la notificación de xms_cc en el token de acceso, si es un valor conocido. El único valor conocido actualmente es cp1.

Los valores no distinguen mayúsculas de minúsculas ni se ordenan. Si se especifica más de un valor en la solicitud de notificación xms_cc, esos valores serán una colección con varios valores como valor de la notificación xms_cc.

Tome la siguiente solicitud como ejemplo:

{ "access_token": { "xms_cc":{"values":["cp1","foo", "bar"] } }}

Esto da como resultado una notificación del siguiente fragmento de código en el token de acceso, si cp1, foo y bar son funcionalidades conocidas.

"xms_cc": ["cp1", "foo", "bar"]

Una vez que se ha solicitado xms_ccla notificación opcional, el manifiesto de la aplicación cambia para tener un aspecto similar al siguiente:

"optionalClaims":
{
    "accessToken": [
    {
        "additionalProperties": [],
        "essential": false,
        "name": "xms_cc",
        "source": null
    }],
    "idToken": [],
    "saml2Token": []
}

A continuación, la API puede personalizar sus respuestas en función de si el cliente es capaz de controlar el desafío de notificaciones o no.

Claim ccClaim = context.User.FindAll(clientCapabilitiesClaim).FirstOrDefault(x => x.Type == "xms_cc");
if (ccClaim != null && ccClaim.Value == "cp1")
{
    // Return formatted claims challenge as this client understands this
}
else
{
    // Throw generic exception
    throw new UnauthorizedAccessException("The caller does not meet the authentication bar to carry our this operation. The service cannot allow this operation");
}

Ejemplos de código

Pasos siguientes