Работа с удостоверениями пользователей при проверке подлинности в Службе приложений Azure

В этой статье показано, как работать с удостоверениями пользователей при использовании встроенной проверки подлинности и авторизации в Служба приложений.

Доступ к утверждениям пользователей в коде приложения

Для всех языковых платформ Служба приложений делает утверждения во входящем токене (поступающем от пользователя, прошедшего проверку подлинности, или клиентского приложения) доступными для вашего кода путем их внедрения в заголовки запроса. Внешние запросы не могут задавать эти заголовки, поэтому они присутствуют только в том случае, если задано Служба приложений. Некоторые примеры заголовков включают:

Верхний колонтитул Description
X-MS-CLIENT-PRINCIPAL Представление доступных утверждений в кодировке Base64 закодировано в формате JSON. Дополнительные сведения см. в разделе "Декодирование заголовка субъекта-клиента".
X-MS-CLIENT-PRINCIPAL-ID Идентификатор вызывающего объекта, заданного поставщиком удостоверений.
X-MS-CLIENT-PRINCIPAL-NAME Имя вызывающего абонента, заданное поставщиком удостоверений, например адрес электронной почты, имя участника-пользователя.
X-MS-CLIENT-PRINCIPAL-IDP Имя поставщика удостоверений, используемого Служба приложений аутентификации.

Маркеры поставщика также предоставляются с помощью аналогичных заголовков. Например, Microsoft Entra также задает X-MS-TOKEN-AAD-ACCESS-TOKEN и X-MS-TOKEN-AAD-ID-TOKEN по необходимости.

Примечание.

В различных языковых платформах эти заголовки могут быть представлены в коде приложения в различных форматах, например строчными или прописными буквами.

Сведения из этих заголовков можно получить с помощью кода, написанного на любом языке или в любой платформе. Декодирование заголовка субъекта-клиента охватывает этот процесс. Для некоторых платформ платформа также предоставляет дополнительные возможности, которые могут быть более удобными.

Декодирование заголовка субъекта-клиента

X-MS-CLIENT-PRINCIPAL содержит полный набор доступных утверждений в формате JSON в кодировке Base64. Эти утверждения проходят процесс сопоставления утверждений по умолчанию, поэтому некоторые из них могут иметь разные имена, чем вы увидите, если обработка маркера напрямую. Декодированные полезные данные структурированы следующим образом:

{
    "auth_typ": "",
    "claims": [
        {
            "typ": "",
            "val": ""
        }
    ],
    "name_typ": "",
    "role_typ": ""
}
Свойство Type Описание:
auth_typ строка Имя поставщика удостоверений, используемого Служба приложений аутентификации.
claims массив объектов Массив объектов, представляющих доступные утверждения. Каждый объект содержит typ и val свойства.
typ строка Имя утверждения. Это может быть подвержено сопоставлению утверждений по умолчанию и может отличаться от соответствующего утверждения, содержащегося в маркере.
val строка Значение утверждения.
name_typ строка Тип утверждения имени, который обычно является универсальным кодом ресурса (URI), предоставляющим сведения о схеме name утверждения, если он определен.
role_typ строка Тип утверждения роли, который обычно является универсальным кодом ресурса (URI), предоставляющим сведения о role схеме утверждения, если он определен.

Чтобы обработать этот заголовок, приложению потребуется декодировать полезные данные и выполнять итерацию по claims массиву, чтобы найти утверждения, интересующие вас. Их можно преобразовать в представление, используемое платформой языка приложения. Ниже приведен пример этого процесса в C#, который создает тип ClaimsPrincipal для используемого приложения:

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

Альтернативные варианты для конкретной платформы

Для приложений ASP.NET 4.6 служба приложений заполняет свойство ClaimsPrincipal.Current утверждениями пользователя, прошедшими проверку подлинности, поэтому вы можете следовать стандартным шаблонам кода .NET, включая атрибут [Authorize]. Аналогичным образом для приложений PHP служба приложений заполняет переменную _SERVER['REMOTE_USER']. Для приложений Java утверждения доступны из сервлета Tomcat.

Для Функции AzureClaimsPrincipal.Current код .NET не заполняется, но вы по-прежнему можете найти утверждения пользователя в заголовках запроса или получить ClaimsPrincipal объект из контекста запроса или даже через параметр привязки. Дополнительные сведения см. в статье "Работа с удостоверениями клиентов" в Функции Azure.

При работе с .NET Core Microsoft.Identity.Web поддерживает заполнение текущего пользователя с использованием функции проверки подлинности Службы приложений. Дополнительные сведения см. на вики-сайте Microsoft.Identity.Web или в руководстве по веб-приложению, которое обращается к Microsoft Graph.

Примечание.

Чтобы сопоставление утверждений работало, необходимо включить хранилище токенов.

Доступ к утверждениям пользователей с помощью API

Если хранилище маркеров включено для приложения, вы также можете получить другие сведения о пользователе, прошедшем /.auth/meпроверку подлинности.

Следующие шаги