Поделиться через


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

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

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

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

Некоторые примеры заголовков описаны в следующей таблице:

Заголовок Описание
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": ""
}
Свойство Тип Описание
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, you 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, and so on. 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 App Service заполняет ClaimsPrincipal.Current утверждениями пользователей, прошедших проверку подлинности. Вы можете следовать стандартному шаблону кода .NET, включая атрибут [Authorize]. Аналогичным образом для приложений PHP служба приложений заполняет переменную _SERVER['REMOTE_USER']. Для приложений Java утверждения доступны из сервлета Tomcat.

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

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

Примечание.

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

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

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