Trabalhar com identidades de utilizador na autenticação Serviço de Aplicações do Azure

Este artigo mostra-lhe como trabalhar com identidades de utilizador ao utilizar a autenticação e autorização incorporadas no Serviço de Aplicações.

Aceder a afirmações de utilizador no código da aplicação

Para todas as arquiteturas de linguagem, Serviço de Aplicações disponibiliza as afirmações no token de entrada (seja de um utilizador final autenticado ou de uma aplicação cliente) ao seu código ao injetá-las nos cabeçalhos do pedido. Os pedidos externos não têm permissão para definir estes cabeçalhos, pelo que só estão presentes se forem definidos por Serviço de Aplicações. Alguns cabeçalhos de exemplo incluem:

Cabeçalho Description
X-MS-CLIENT-PRINCIPAL Uma representação JSON codificada com Base64 de afirmações disponíveis. Para obter mais informações, veja Descodificar o cabeçalho do principal de cliente.
X-MS-CLIENT-PRINCIPAL-ID Um identificador para o autor da chamada definido pelo fornecedor de identidade.
X-MS-CLIENT-PRINCIPAL-NAME Um nome legível por humanos para o autor da chamada definido pelo fornecedor de identidade, por exemplo, Email Endereço, Nome Principal de Utilizador.
X-MS-CLIENT-PRINCIPAL-IDP O nome do fornecedor de identidade utilizado pelo Serviço de Aplicações Authentication.

Os tokens de fornecedor também são expostos através de cabeçalhos semelhantes. Por exemplo, o Fornecedor de Identidade da Microsoft também define X-MS-TOKEN-AAD-ACCESS-TOKEN e X-MS-TOKEN-AAD-ID-TOKEN conforme adequado.

Nota

Diferentes arquiteturas de linguagem podem apresentar estes cabeçalhos ao código da aplicação em formatos diferentes, como minúsculas ou maiúsculas/minúsculas.

O código escrito em qualquer linguagem ou arquitetura pode obter as informações de que precisa a partir destes cabeçalhos. A descodificação do cabeçalho do principal de cliente abrange este processo. Para algumas arquiteturas, a plataforma também fornece opções adicionais que podem ser mais convenientes.

Descodificar o cabeçalho do principal de cliente

X-MS-CLIENT-PRINCIPAL contém o conjunto completo de afirmações disponíveis como JSON codificado com Base64. Estas afirmações passam por um processo de mapeamento de afirmações predefinido, pelo que algumas podem ter nomes diferentes dos que veria se o processamento do token era processado diretamente. O payload descodificado é estruturado da seguinte forma:

{
    "auth_typ": "",
    "claims": [
        {
            "typ": "",
            "val": ""
        }
    ],
    "name_typ": "",
    "role_typ": ""
}
Propriedade Tipo Description
auth_typ cadeia (de carateres) O nome do fornecedor de identidade utilizado pelo Serviço de Aplicações Authentication.
claims matriz de objetos Uma matriz de objetos que representam as afirmações disponíveis. Cada objeto contém typ e val propriedades.
typ string O nome da afirmação. Isto pode estar sujeito ao mapeamento de afirmações predefinido e pode ser diferente da afirmação correspondente contida num token.
val string O valor da afirmação.
name_typ string O tipo de afirmação de nome, que normalmente é um URI que fornece informações do esquema sobre a name afirmação, se estiver definido.
role_typ string O tipo de afirmação de função, que normalmente é um URI que fornece informações do esquema sobre a role afirmação, se estiver definido.

Para processar este cabeçalho, a sua aplicação terá de descodificar o payload e iterar através da claims matriz para encontrar as afirmações de interesse. Pode ser conveniente convertê-los numa representação utilizada pela arquitetura de linguagem da aplicação. Eis um exemplo deste processo em C# que constrói um tipo ClaimsPrincipal para a aplicação utilizar:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Http;

public static class ClaimsPrincipalParser
{
    private class ClientPrincipalClaim
    {
        [JsonPropertyName("typ")]
        public string Type { get; set; }
        [JsonPropertyName("val")]
        public string Value { get; set; }
    }

    private class ClientPrincipal
    {
        [JsonPropertyName("auth_typ")]
        public string IdentityProvider { get; set; }
        [JsonPropertyName("name_typ")]
        public string NameClaimType { get; set; }
        [JsonPropertyName("role_typ")]
        public string RoleClaimType { get; set; }
        [JsonPropertyName("claims")]
        public IEnumerable<ClientPrincipalClaim> Claims { get; set; }
    }

    public static ClaimsPrincipal Parse(HttpRequest req)
    {
        var principal = new ClientPrincipal();

        if (req.Headers.TryGetValue("x-ms-client-principal", out var header))
        {
            var data = header[0];
            var decoded = Convert.FromBase64String(data);
            var json = Encoding.UTF8.GetString(decoded);
            principal = JsonSerializer.Deserialize<ClientPrincipal>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
        }

        /** 
         *  At this point, the code can iterate through `principal.Claims` to
         *  check claims as part of validation. Alternatively, we can convert
         *  it into a standard object with which to perform those checks later
         *  in the request pipeline. That object can also be leveraged for 
         *  associating user data, etc. The rest of this function performs such
         *  a conversion to create a `ClaimsPrincipal` as might be used in 
         *  other .NET code.
         */

        var identity = new ClaimsIdentity(principal.IdentityProvider, principal.NameClaimType, principal.RoleClaimType);
        identity.AddClaims(principal.Claims.Select(c => new Claim(c.Type, c.Value)));
        
        return new ClaimsPrincipal(identity);
    }
}

Alternativas específicas da arquitetura

Para ASP.NET aplicações 4.6, Serviço de Aplicações preenche ClaimsPrincipal.Current com as afirmações do utilizador autenticado, para que possa seguir o padrão de código .NET padrão, incluindo o [Authorize] atributo. Da mesma forma, para aplicações PHP, Serviço de Aplicações preenche a _SERVER['REMOTE_USER'] variável. Para aplicações Java, as afirmações são acessíveis a partir do servlet Tomcat.

Para Funções do Azure, ClaimsPrincipal.Current não é preenchido para o código .NET, mas ainda pode encontrar as afirmações de utilizador nos cabeçalhos do pedido ou obter o ClaimsPrincipal objeto a partir do contexto do pedido ou mesmo através de um parâmetro de enlace. Para obter mais informações, veja Trabalhar com identidades de cliente no Funções do Azure.

Para o .NET Core, o Microsoft.Identity.Web suporta o povoamento do utilizador atual com Serviço de Aplicações autenticação. Para saber mais, pode ler sobre o mesmo no wiki Microsoft.Identity.Web ou vê-lo demonstrado neste tutorial para uma aplicação Web aceder ao Microsoft Graph.

Nota

Para que o mapeamento de afirmações funcione, tem de ativar o arquivo de Tokens.

Aceder a afirmações de utilizador com a API

Se o arquivo de tokens estiver ativado para a sua aplicação, também pode obter outros detalhes sobre o utilizador autenticado ao chamar /.auth/me.

Passos seguintes