Маркеры подтверждения владения (PoP)

Токены на предъявителя являются стандартом в современных процессах управления идентификацией; однако их можно похитить из кэшей токенов.

Маркеры подтверждения владения (PoP), как описано RFC 7800, устраняют эту угрозу. Токены PoP привязываются к клиентскому устройству с помощью пары открытого и закрытого ключей PoP. Открытый ключ PoP внедряется в маркер издателем маркера (Entra ID), а клиент также подписывает маркер с помощью закрытого ключа PoP. Полностью сформированный маркер PoP имеет две цифровые подписи — один из издателя токенов и один из клиента. Протокол PoP имеет две защиты:

  • Защита от компрометации кэша маркеров. MSAL не будет хранить полностью сформированные токены PoP в кэше. Вместо этого оно будет подписывать токены только тогда, когда приложение их запрашивает. Злоумышленник, который может скомпрометировать кэш токенов, не должен иметь возможности цифрово подписывать находящиеся в нём неполные токены, так как у него нет доступа к приватному ключу PoP. Возможность злоумышленника украсть закрытый ключ может быть устранена с помощью аппаратных защищенных ключей.
  • Защита от атак типа «человек посередине». В протокол добавляется серверный нонс.

Предупреждение

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

Варианты PoP

Существует несколько протоколов PoP и их вариантов. Инфраструктура Microsoft Entra ID направлена на поддержку двух типов:

  • mTLS POP — RFC 8705. Предназначено для межсервисного взаимодействия, например для рабочих нагрузок, получающих секреты из Azure Key Vault.
  • DPOP — RFC 9449. Предназначено для общедоступных клиентских приложений.

Почему 2 протокола? MTLS POP быстрее и имеет преимущество включения нецелевой защиты на уровне TLS; однако может быть трудно установить туннели mTLS между клиентом и поставщиком удостоверений, а также между клиентом и ресурсом. dPOP не требует изменений транспортного протокола; однако nonce сервера должен явно обрабатываться разработчиком приложения.

Поддержка устаревших версий PoP SHR

Microsoft обеспечила поддержку PoP с помощью подписанного HTTP-запроса (SHR) . Подробные спецификации см. в разделе распределения ключей PoP и SHR . Этот протокол поэтапно отменяется и заменяется DPOP.

Валидация токенов

Microsoft предоставляет для .NET базовые средства проверки токенов через https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet — оба типа токенов можно проверять таким способом.

Usage

Общедоступные клиентские приложения

С помощью брокера Windows (WAM) можно реализовать PoP в потоках общедоступного клиента. Другие библиотеки MSAL также поддерживают PoP через WAM.

Брокер (через MSAL) будет использовать лучшие доступные ключи, которые существуют на компьютере, как правило, аппаратные ключи (например, TPM). Нет возможности принести собственный ключ.

Возможно, клиент не поддерживает создание токенов PoP. Это вызвано тем, что брокеры (например, WAM или Корпоративный портал) не всегда присутствуют на устройстве или пакет SDK не реализует протокол в определенной операционной системе. В настоящее время маркеры PoP доступны в Windows 10 и более поздних версиях, а также Windows Server 2019 и более поздних версиях. Используйте IsProofOfPossessionSupportedByClient(), чтобы проверить, поддерживается ли PoP клиентом.

Пример

// Required for the use of the broker 
using Microsoft.Identity.Client.Broker; 

// The PoP token will be bound to this user / machine and to `GET https://www.contoso.com/tranfers` (the query parameters are not bound).
// The nonce is a requirement in this case and needs to be acquired from the resource before using this API.

// Server nonce is required
string nonce = "nonce";

//HttpMethod is optional
HttpMethod method = HttpMethod.Get;

//Request URI
Uri requestUri = new Uri("https://www.contoso.com/tranfers?user=me");
          
var pca = PublicClientApplicationBuilder.Create(CLIENT_ID)
    .WithBroker()  //Enables the use of broker on public clients only
    .Build();

//Interactive request
AuthenticationResult result = await pca
      .AcquireTokenInteractive(new[] { "scope" })
      .WithProofOfPossession(nonce, method, requestUri)
      .ExecuteAsync()
      .ConfigureAwait(false);

// The PoP token will be available in the AuthenticationResult.AccessToken returned form the acquire token call

//To create the auth header
var authHeader = new AuthenticationHeaderValue(result.TokenType, result.AccessToken);

//Silent request
var accounts = await pca.GetAccountsAsync().ConfigureAwait(false);
var result = await pca.AcquireTokenSilent(new[] { "scope" }, accounts.FirstOrDefault())
       .WithProofOfPossession(nonce, method, requestUri)
       .ExecuteAsync()
       .ConfigureAwait(false);

Добавление дополнительных утверждений или создание части SHR-запроса токена PoP

Чтобы создать SHR самостоятельно, ознакомьтесь с примером реализации.