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

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

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

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

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

Маркеры поставщика также предоставляются через аналогичные заголовки. Например, поставщик удостоверений Майкрософт также задает 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": ""
}
Свойство Тип Описание
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

Дальнейшие действия