Desafios de reivindicações, solicitações de solicitações e recursos do cliente

Um desafio de declarações é uma resposta enviada de uma API indicando que um token de acesso enviado por um aplicativo cliente tem declarações insuficientes. Isso pode ocorrer porque o token não satisfaz as políticas de Acesso Condicional definidas para essa API ou porque o token de acesso foi revogado.

Uma solicitação de declarações é feita pelo aplicativo cliente para redirecionar o usuário de volta ao provedor de identidade para recuperar um novo token com declarações que satisfaçam os outros requisitos que não foram atendidos.

Os aplicativos que usam recursos de segurança aprimorados, como CAE (Avaliação Contínua de Acesso) e contexto de autenticação de Acesso Condicional, devem estar preparados para lidar com desafios de declarações.

Seu aplicativo recebe desafios de declarações de serviços populares como o Microsoft Graph somente se declarar seus recursos de cliente em suas chamadas para o serviço.

Formato de cabeçalho de contestação de declarações

O desafio de declarações é uma diretiva como um www-authenticate cabeçalho retornado por uma API quando um token de acesso apresentado a ela não é autorizado, e um novo token de acesso com os recursos certos é necessário. O desafio de declarações compreende várias partes: o código de status HTTP da resposta e o www-authenticate cabeçalho, que tem várias partes e deve conter uma diretiva de declarações.

Eis um exemplo:

HTTP 401; Unauthorized

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

Código de status HTTP: Deve ser 401 Não autorizado.

www-authenticate cabeçalho de resposta contendo:

Parâmetro Obrigatório/opcional Description
Authentication type Necessário Deve ser portador.
Realm Opcional O ID do locatário ou nome de domínio do locatário (por exemplo, microsoft.com) que está sendo acessado. DEVE ser uma cadeia de caracteres vazia no caso em que a autenticação passa pelo ponto de extremidade comum.
authorization_uri Necessário O URI do authorize ponto de extremidade onde uma autenticação interativa pode ser executada, se necessário. Se especificado no realm, as informações do locatário DEVEM ser incluídas no authorization_uri. Se realm for uma cadeia de caracteres vazia, o authorization_uri DEVE ser contra o ponto de extremidade comum.
error Necessário Deve ser "insufficient_claims" quando uma contestação de reivindicações deve ser gerada.
claims Necessário quando o erro é "insufficient_claims". Uma cadeia de caracteres entre aspas contendo uma solicitação de declarações codificada com base 64. A solicitação de declarações deve solicitar declarações para o "access_token" no nível superior do objeto JSON. O valor (declarações solicitadas) será dependente do contexto e especificado posteriormente neste documento. Por motivos de tamanho, os aplicativos de terceira parte confiável DEVEM minar o JSON antes da codificação base 64. O JSON bruto do exemplo acima é {"access_token":{"acrs":{"essential":true,"value":"cp1"}}}.

A resposta 401 pode conter mais de um www-authenticate cabeçalho. Todos os campos da tabela anterior devem estar contidos no mesmo www-authenticate cabeçalho. O www-authenticate cabeçalho que contém o desafio de declarações pode conter outros campos. Os campos no cabeçalho não estão ordenados. De acordo com a RFC 7235, cada nome de parâmetro deve ocorrer apenas uma vez por desafio de esquema de autenticação.

Pedido de sinistros

Quando um aplicativo recebe um desafio de declarações, isso indica que o token de acesso anterior não é mais considerado válido. Nesse cenário, o aplicativo deve limpar o token de qualquer cache local ou sessão de usuário. Em seguida, ele deve redirecionar o usuário conectado de volta para o Microsoft Entra ID para recuperar um novo token usando o fluxo de código de autorização OAuth 2.0 com um parâmetro de declarações que satisfará os outros requisitos que não foram atendidos.

Eis um exemplo:

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

O desafio de declarações deve ser passado como parte de todas as chamadas para um ponto de extremidade do Microsoft Entra /authorize até que um token seja recuperado com êxito. Depois que o token é recuperado, ele não é mais necessário.

Para preencher o parâmetro de declarações, o desenvolvedor deve:

  1. Decodifice a cadeia de caracteres base64 recebida anteriormente.
  2. URL-codificar a cadeia de caracteres e adicionar novamente ao parâmetro claims .

Após a conclusão desse fluxo, o aplicativo recebe um token de acesso que possui as outras declarações que provam que o usuário satisfez as condições exigidas.

Capacidades do cliente

Os recursos do cliente ajudam um provedor de recursos, como uma API da Web, a detetar se o aplicativo cliente chamador entende o desafio de declarações e, em seguida, pode personalizar sua resposta de acordo. Esse recurso pode ser útil quando nem todos os clientes de API são capazes de lidar com desafios de reivindicação, e algumas versões anteriores ainda esperam uma resposta diferente.

Alguns aplicativos populares, como o Microsoft Graph , enviam desafios de declarações somente se o aplicativo cliente de chamada declarar que é capaz de lidar com eles usando recursos de cliente.

Para evitar tráfego extra ou impactos na experiência do usuário, o Microsoft Entra ID não pressupõe que seu aplicativo possa lidar com declarações contestadas, a menos que você opte explicitamente por participar. Um aplicativo não receberá desafios de declarações (e não poderá usar os recursos relacionados, como tokens CAE), a menos que declare que está pronto para lidar com eles com o recurso "cp1".

Como comunicar os recursos do cliente para o Microsoft Entra ID

O parâmetro de declarações de exemplo a seguir mostra como um aplicativo cliente comunica sua capacidade ao Microsoft Entra ID em um fluxo de código de autorização OAuth 2.0.

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

Use o seguinte código se você usar a biblioteca MSAL:

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

Aqueles que usam Microsoft.Identity.Web podem adicionar o seguinte código ao arquivo de configuração:

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

Consulte o seguinte trecho para ver uma solicitação de exemplo para o 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

Quando você já tiver uma carga existente para o parâmetro de declarações, adicioná-la ao conjunto existente.

Por exemplo, se você já tiver a seguinte resposta de uma operação de contexto de autenticação de Acesso a Condição;

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

Você anteciparia a capacidade do cliente na carga útil de sinistros existente.

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

Receber xms_cc declaração num token de acesso

Para receber informações sobre se os aplicativos cliente podem lidar com desafios de declarações, um implementador de API deve solicitar xms_cc como uma declaração opcional em seu manifesto de aplicativo.

A declaração xms_cc com um valor de "cp1" no token de acesso é a maneira autorizada de identificar que um aplicativo cliente é capaz de lidar com um desafio de declarações. xms_cc é uma declaração opcional que nem sempre será emitida no token de acesso, mesmo que o cliente envie uma solicitação de declaração com "xms_cc". Para que um token de acesso contenha a declaração xms_cc, o aplicativo de recurso (ou seja, o implementador de API) deve solicitar xms_cc como uma declaração opcional em seu manifesto do aplicativo. Quando solicitado como uma declaração opcional, xms_cc é adicionado ao token de acesso somente se o aplicativo cliente enviar xms_cc na solicitação de declarações. O valor da solicitação de declaração de xms_cc é incluído como o valor da declaração de xms_cc no token de acesso, se for um valor conhecido. O único valor conhecido atualmente é cp1.

Os valores não diferenciam maiúsculas de minúsculas nem são ordenados. Se mais de um valor for especificado na solicitação de declaração de xms_cc , esses valores serão uma coleção de vários valores como o valor da xms_cc declaração.

Tomemos como exemplo o seguinte pedido:

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

Isso resulta em uma reivindicação do seguinte trecho no token de acesso, se cp1, foo e bar forem recursos conhecidos.

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

Depois que a xms_ccdeclaração opcional for solicitada, o manifesto do aplicativo mudará para ter a seguinte aparência:

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

A API pode então personalizar suas respostas com base em se o cliente é capaz de lidar com o desafio de reivindicações ou não.

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

Amostras de código

Próximos passos