Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Note
Nem todos os clientes podem obter certificados PoP mTLS porque esta funcionalidade está atualmente em pré-visualização privada.
A associação de token ao certificado (também conhecida como mTLS PoP - Mutual TLS Proof-of-Possession) é uma funcionalidade de segurança avançada que realiza a vinculação criptográfica de tokens de acesso a um certificado X.509 específico. O RFC 8705 descreve esta ligação. A ligação garante que, mesmo que um token seja intercetado, um atacante não pode usá-lo sem possuir a chave privada correspondente.
Compreenda como funciona a ligação de tokens
Os passos seguintes descrevem o fluxo de ligação de tokens desde a aquisição até à verificação.
- Aquisição de Tokens: Ao solicitar um token de acesso com ligação de token ativada, Microsoft Identity Web inclui a impressão digital do certificado no pedido do token
-
Ligação de Token: O servidor de autorização incorpora uma
cnfreivindicação (de confirmação) no token emitido contendo a impressão digital SHA-256 do certificado (x5t#S256) - Chamada API: O cliente apresenta tanto o token associado como o certificado ao chamar a API a jusante
-
Verificação: A API valida que o certificado apresentado corresponde à referência do certificado na reivindicação
cnfdo token
sequenceDiagram
participant Client
participant EntraID as Microsoft Entra ID
participant API
Client->>EntraID: Token request with certificate thumbprint
EntraID->>Client: Token with cnf claim (bound to certificate)
Client->>API: MTLS_POP token + Client certificate
API->>API: Validate token and certificate binding
API->>Client: Protected resource
Analise os benefícios de segurança
A ligação de tokens oferece as seguintes vantagens para proteger as suas aplicações.
- Proteção contra Roubo de Tokens: Os tokens roubados são inúteis sem o certificado correspondente
- Prevenção de Ataques de Replay: Os tokens não podem ser retransmitidos por diferentes clientes
- Autenticação Melhorada: Combina "algo que tens" (certificado) com fluxos OAuth2 tradicionais
- Confiança Zero Arquitetura: Alinha-se com os princípios zero trust ao vincular credenciais a dispositivos específicos
Configurar ligação de tokens
Configure tanto a aplicação cliente como o servidor API para permitir a ligação de tokens PoP mTLS.
Configurar o aplicativo cliente
Complete os seguintes passos para configurar a aplicação cliente para a ligação de tokens.
1. Configurar as definições do Microsoft Entra ID
No seu appsettings.json, configure as suas definições do Microsoft Entra, incluindo o certificado.
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "your-tenant-id",
"ClientId": "your-client-id",
"ClientCredentials": [
{
"SourceType": "StoreWithDistinguishedName",
"CertificateStorePath": "CurrentUser/My",
"CertificateDistinguishedName": "CN=YourCertificate"
}
],
"SendX5c": true
}
}
2. Configurar a API descendente com associação de token
Configure a sua secção de API a jusante com o esquema de MTLS_POP protocolo:
{
"DownstreamApi": {
"BaseUrl": "https://api.contoso.com/",
"RelativePath": "api/data",
"ProtocolScheme": "MTLS_POP",
"RequestAppToken": true,
"Scopes": [ "api://your-api-scope/.default" ]
}
}
Propriedades Importantes de Configuração:
-
ProtocolScheme: Deve ser definido para"MTLS_POP"para ativar a ligação de tokens -
RequestAppToken: Deve sertrue(a ligação de tokens atualmente suporta apenas tokens de aplicação) -
Scopes: Escopos de API necessários para a chamada de API descendente
3. Serviços de registo
Registe o serviço de API a jusante no código de arranque da sua aplicação. O exemplo seguinte mostra tanto as abordagens da aplicação de consola como do ASP.NET Core.
using Microsoft.Identity.Web;
var builder = WebApplication.CreateBuilder(args);
// Option 1: Using TokenAcquirerFactory (for console apps, background services)
var tokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance();
tokenAcquirerFactory.Services.AddDownstreamApi(
"DownstreamApi",
tokenAcquirerFactory.Configuration.GetSection("DownstreamApi"));
var serviceProvider = tokenAcquirerFactory.Build();
// Option 2: Using ASP.NET Core DI (for web apps, web APIs)
builder.Services.AddAuthentication()
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddDownstreamApi(
"DownstreamApi",
builder.Configuration.GetSection("DownstreamApi"));
Configurar o servidor API
A API a jusante deve validar tanto o token como a ligação do certificado. Aqui está um exemplo completo:
1. Registar gestores de autenticação
using Microsoft.Identity.Web;
var builder = WebApplication.CreateBuilder(args);
// Add standard JWT Bearer authentication
builder.Services.AddMicrosoftIdentityWebApiAuthentication(builder.Configuration);
// Add custom MTLS_POP authentication handler
builder.Services.AddAuthentication()
.AddScheme<AuthenticationSchemeOptions, MtlsPopAuthenticationHandler>(
"MTLS_POP",
options => { });
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
2. Implementar o handler de autenticação PoP mTLS
using System.Security.Claims;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text.Encodings.Web;
using System.Text.Json;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens;
public class MtlsPopAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
public const string ProtocolScheme = "MTLS_POP";
public MtlsPopAuthenticationHandler(
IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger,
UrlEncoder encoder)
: base(options, logger, encoder)
{
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
// 1. Extract the MTLS_POP authorization header
var authHeader = Request.Headers.Authorization.FirstOrDefault();
if (string.IsNullOrEmpty(authHeader) ||
!authHeader.StartsWith($"{ProtocolScheme} ", StringComparison.OrdinalIgnoreCase))
{
return AuthenticateResult.NoResult();
}
var authToken = authHeader.Substring($"{ProtocolScheme} ".Length).Trim();
try
{
// 2. Parse the JWT token
var handler = new JsonWebTokenHandler();
var token = handler.ReadJsonWebToken(authToken);
// 3. Extract the 'cnf' claim
var cnfClaim = token.Claims.FirstOrDefault(c => c.Type == "cnf");
if (cnfClaim == null)
{
return AuthenticateResult.Fail("Missing 'cnf' claim in MTLS_POP token");
}
// 4. Extract certificate thumbprint from cnf claim
var cnfJson = JsonDocument.Parse(cnfClaim.Value);
if (!cnfJson.RootElement.TryGetProperty("x5t#S256", out var x5tS256Element))
{
return AuthenticateResult.Fail("Missing 'x5t#S256' in cnf claim");
}
var expectedThumbprint = x5tS256Element.GetString();
// 5. Get client certificate from TLS connection
var clientCert = Context.Connection.ClientCertificate;
if (clientCert != null)
{
var actualThumbprint = GetCertificateThumbprint(clientCert);
// 6. Validate certificate binding
if (!string.Equals(actualThumbprint, expectedThumbprint,
StringComparison.OrdinalIgnoreCase))
{
return AuthenticateResult.Fail(
"Certificate thumbprint mismatch with cnf claim");
}
}
// 7. Create claims principal
var claims = token.Claims.Select(c => new Claim(c.Type, c.Value)).ToList();
var identity = new ClaimsIdentity(claims, ProtocolScheme);
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, ProtocolScheme);
return AuthenticateResult.Success(ticket);
}
catch (Exception ex)
{
Logger.LogError(ex, "Error validating mTLS PoP token");
return AuthenticateResult.Fail($"Validation error: {ex.Message}");
}
}
private static string GetCertificateThumbprint(X509Certificate2 certificate)
{
using var sha256 = SHA256.Create();
var hash = sha256.ComputeHash(certificate.RawData);
return Base64UrlEncoder.Encode(hash);
}
}
Usar ligação de tokens em aplicações
Os exemplos seguintes mostram como integrar a ligação de tokens PoP mTLS em diferentes tipos de aplicação.
Chamar APIs a partir de uma aplicação de consola ou daemonizada
O exemplo seguinte demonstra uma aplicação de consola ou daemon que invoca uma API a jusante com associação de token PoP mTLS.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Identity.Abstractions;
using Microsoft.Identity.Web;
public class Program
{
public static async Task Main(string[] args)
{
// Create and configure token acquirer
var tokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance();
tokenAcquirerFactory.Services.AddDownstreamApi(
"SecureApi",
tokenAcquirerFactory.Configuration.GetSection("SecureApi"));
var serviceProvider = tokenAcquirerFactory.Build();
// Get IDownstreamApi instance
var downstreamApi = serviceProvider.GetRequiredService<IDownstreamApi>();
// Call API with mTLS PoP token
var response = await downstreamApi.GetForAppAsync<ApiResponse>("SecureApi");
Console.WriteLine($"Result: {response?.Data}");
}
}
public class ApiResponse
{
public string? Data { get; set; }
}
APIs de chamadas a partir de uma aplicação web ASP.NET Core
O exemplo seguinte mostra um controlador que efetua uma chamada para uma API a jusante com binding de tokens PoP mTLS.
using Microsoft.AspNetCore.Mvc;
using Microsoft.Identity.Abstractions;
[ApiController]
[Route("api/[controller]")]
public class DataController : ControllerBase
{
private readonly IDownstreamApi _downstreamApi;
private readonly ILogger<DataController> _logger;
public DataController(
IDownstreamApi downstreamApi,
ILogger<DataController> logger)
{
_downstreamApi = downstreamApi;
_logger = logger;
}
[HttpGet]
public async Task<IActionResult> GetSecureData()
{
try
{
// Call downstream API with mTLS PoP token binding
var data = await _downstreamApi.GetForAppAsync<SecureData>(
"SecureApi");
return Ok(data);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to retrieve secure data");
return StatusCode(500, "Failed to retrieve data");
}
}
}
public class SecureData
{
public string? Id { get; set; }
public string? Value { get; set; }
}
Configurar DownstreamApiOptions programaticamente
O exemplo seguinte define as opções MTLS PoP diretamente em código em vez de ficheiros de configuração.
using Microsoft.Identity.Abstractions;
using Microsoft.Identity.Web;
public class SecureApiService
{
private readonly IDownstreamApi _downstreamApi;
public SecureApiService(IDownstreamApi downstreamApi)
{
_downstreamApi = downstreamApi;
}
public async Task<T?> CallSecureApiAsync<T>(string endpoint) where T : class
{
return await _downstreamApi.GetForAppAsync<T>(
serviceName: null,
downstreamApiOptionsOverride: options =>
{
options.BaseUrl = "https://api.secure.com";
options.RelativePath = endpoint;
options.ProtocolScheme = "MTLS_POP";
options.RequestAppToken = true;
options.Scopes = new[] { "api://secure-api/.default" };
});
}
}
Utilizar MicrosoftIdentityMessageHandler com ligação de token
MicrosoftIdentityMessageHandler suporta a vinculação de tokens PoP mTLS através dos métodos de extensão AddMicrosoftIdentityMessageHandler. Quando ProtocolScheme está definido para "MTLS_POP", o handler adquire automaticamente um token vinculado e envia pedidos através de um cliente HTTP configurado em mTLS.
Configurar opções em linha
O exemplo seguinte regista um cliente HTTP com configuração MTLS PoP inline e mostra a sua utilização num serviço.
// Program.cs
services.AddHttpClient("MtlsPopClient", client =>
{
client.BaseAddress = new Uri("https://api.contoso.com");
})
.AddMicrosoftIdentityMessageHandler(options =>
{
options.Scopes.Add("api://contoso/.default");
options.ProtocolScheme = "MTLS_POP";
options.RequestAppToken = true;
});
// Usage in a service
public class SecureApiService
{
private readonly HttpClient _httpClient;
public SecureApiService(IHttpClientFactory factory)
{
_httpClient = factory.CreateClient("MtlsPopClient");
}
public async Task<string> GetSecureDataAsync()
{
// Authentication and mTLS certificate binding are automatic
var response = await _httpClient.GetAsync("/api/secure-data");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
Carregar configuração de appsettings.json
Também podes carregar as definições de associação de tokens a partir do teu ficheiro de configuração.
appsettings.json:
{
"DownstreamApis": {
"SecureApi": {
"Scopes": ["api://secure-api/.default"],
"ProtocolScheme": "MTLS_POP",
"RequestAppToken": true
}
}
}
Program.cs: O código seguinte regista o cliente HTTP usando a secção de configuração.
services.AddHttpClient("SecureApiClient", client =>
{
client.BaseAddress = new Uri("https://secure-api.example.com");
})
.AddMicrosoftIdentityMessageHandler(
configuration.GetSection("DownstreamApis:SecureApi"),
"SecureApi");
Aplicar ligação de token por solicitação
Use opções por pedido quando alguns pedidos precisam de vinculação de token e outros não.
services.AddHttpClient("FlexibleClient")
.AddMicrosoftIdentityMessageHandler();
// In a service:
public async Task<string> CallWithTokenBindingAsync()
{
var request = new HttpRequestMessage(HttpMethod.Get, "https://api.contoso.com/secure")
.WithAuthenticationOptions(options =>
{
options.Scopes.Add("api://contoso/.default");
options.ProtocolScheme = "MTLS_POP";
options.RequestAppToken = true;
});
var response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
Para mais informações sobre MicrosoftIdentityMessageHandler, consulte a documentação de APIs Personalizadas.
Crie um HttpClient personalizado com provedor de cabeçalhos de autorização
Use esta abordagem para cenários que exijam mais controlo sobre pedidos HTTP. O exemplo seguinte adquire um cabeçalho de autorização limitada e cria um cliente HTTP configurado em mTLS.
using Microsoft.Identity.Abstractions;
using System.Net.Http.Headers;
public class CustomApiClient
{
private readonly IAuthorizationHeaderProvider _authProvider;
private readonly IHttpClientFactory _httpClientFactory;
public CustomApiClient(
IAuthorizationHeaderProvider authProvider,
IHttpClientFactory httpClientFactory)
{
_authProvider = authProvider;
_httpClientFactory = httpClientFactory;
}
public async Task<string> CallApiWithCustomLogicAsync()
{
// Create downstream API options for mTLS PoP
var apiOptions = new DownstreamApiOptions
{
BaseUrl = "https://api.contoso.com",
ProtocolScheme = "MTLS_POP",
RequestAppToken = true,
Scopes = new[] { "api://contoso/.default" }
};
// Get authorization header with binding certificate info
var authResult = await (_authProvider as IBoundAuthorizationHeaderProvider)
?.CreateBoundAuthorizationHeaderAsync(apiOptions)!;
if (authResult.IsSuccess)
{
// Create HTTP client with certificate binding
var httpClient = authResult.Value.BindingCertificate != null
? CreateMtlsHttpClient(authResult.Value.BindingCertificate)
: _httpClientFactory.CreateClient();
// Set authorization header
httpClient.DefaultRequestHeaders.Authorization =
AuthenticationHeaderValue.Parse(authResult.Value.AuthorizationHeaderValue);
// Make API call
var response = await httpClient.GetAsync(
$"{apiOptions.BaseUrl}/api/endpoint");
return await response.Content.ReadAsStringAsync();
}
throw new InvalidOperationException("Failed to acquire token");
}
private HttpClient CreateMtlsHttpClient(X509Certificate2 certificate)
{
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(certificate);
return new HttpClient(handler);
}
}
Analisar a estrutura dos tokens
Os exemplos seguintes mostram como os tokens standard e bound diferem.
Compare os tokens padrão OAuth2
Um token OAuth2 padrão não contém informação de ligação de certificados.
{
"aud": "api://your-api",
"iss": "https://login.microsoftonline.com/tenant-id/",
"iat": 1234567890,
"exp": 1234571490,
"appid": "client-id",
"tid": "tenant-id"
}
Revise tokens mTLS PoP com binding
Um token PoP mTLS inclui a cnf reivindicação que vincula o token a um certificado específico.
{
"aud": "api://your-api",
"iss": "https://login.microsoftonline.com/tenant-id/",
"iat": 1234567890,
"exp": 1234571490,
"appid": "client-id",
"tid": "tenant-id",
"cnf": {
"x5t#S256": "buc7x2HxS_hPnVJb9J5mwPr6jCw8Y_2LHDz-gp_-6KM"
}
}
A reivindicação (confirmação) cnf contém a impressão digital SHA-256 do certificado, que está codificada em Base64Url.
Compreender as limitações atuais
Reveja as seguintes restrições antes de implementar a ligação de tokens PoP mTLS.
Suporta apenas tokens de aplicação
Atualmente, a ligação de tokens suporta apenas tokens de aplicação (tokens apenas para aplicação). Tokens delegados (de utilizador) não são suportados.
Definir o esquema do protocolo
A ProtocolScheme propriedade deve estar explicitamente definida como "MTLS_POP" para permitir a ligação de tokens. Se não estiver definido, é usada a autenticação padrão do Portador.
Cumprir os requisitos do certificado
- O certificado deve ser configurado em
ClientCredentialscomSendX5cdefinido comotrue - O certificado deve estar acessível no momento da aquisição do token
Resolver problemas comuns
Use as seguintes orientações para diagnosticar e resolver problemas de ligação de tokens.
Resolver Problemas Comuns
Falta de declaração 'cnf' no token
Causa: A ligação do token não foi devidamente configurada ou o token é um token Bearer padrão.
Solução: Verificar que ProtocolScheme está definido para "MTLS_POP" e RequestAppToken é true.
{
"DownstreamApi": {
"ProtocolScheme": "MTLS_POP", // ensure this is set
"RequestAppToken": true
}
}
2. "Incompatibilidade da impressão digital (thumbprint) do certificado"
Causa: O certificado apresentado à API não corresponde ao usado para aquisição de tokens.
Solução:
- Verifique se o mesmo certificado é usado tanto para aquisição de tokens como para chamadas API
- Verifique a configuração de carregamento do certificado em
ClientCredentials - Certifique-se de que o certificado não está expirado nem renovado
3. "Falta um certificado, que é necessário para a vinculação de tokens"
Cause: Nenhum certificado está configurado nas definições Microsoft Entra.
Solução: Adicione um certificado à sua ClientCredentials configuração e defina SendX5c para true.
{
"AzureAd": {
"ClientCredentials": [
{
"SourceType": "StoreWithDistinguishedName",
"CertificateStorePath": "CurrentUser/My",
"CertificateDistinguishedName": "CN=YourCertificate"
}
],
"SendX5c": true // required for token binding
}
}
4. "A ligação de token requer aquisição de token de aplicação ativada"
Causa: RequestAppToken não está definido para true.
Solução: Defina RequestAppToken como true nas suas opções.
var options = new DownstreamApiOptions
{
ProtocolScheme = "MTLS_POP",
RequestAppToken = true, // must be true
};
Ligação de tokens de depuração
Utilize as seguintes técnicas para investigar questões relacionadas com a ligação de tokens.
Ativar registo detalhado
Adicione a seguinte configuração para permitir o registo de nível de depuração para Microsoft.Identity.Web.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Identity.Web": "Debug"
}
}
}
Inspecionar as declarações do token
Use o seguinte código para listar todas as reivindicações num token e verificar a reivindicação cnf .
var handler = new JsonWebTokenHandler();
var token = handler.ReadJsonWebToken(tokenString);
foreach (var claim in token.Claims)
{
Console.WriteLine($"{claim.Type}: {claim.Value}");
}
// Look for 'cnf' claim with x5t#S256
var cnfClaim = token.Claims.FirstOrDefault(c => c.Type == "cnf");
Verificar impressão digital do certificado
Use o seguinte código para calcular e exibir a impressão digital SHA-256 de um certificado para comparação.
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Microsoft.IdentityModel.Tokens;
var cert = new X509Certificate2("path/to/cert.pfx", "password");
using var sha256 = SHA256.Create();
var hash = sha256.ComputeHash(cert.RawData);
var thumbprint = Base64UrlEncoder.Encode(hash);
Console.WriteLine($"Certificate thumbprint: {thumbprint}");
Siga as diretrizes de segurança
Aplique as seguintes práticas de segurança ao implementar a vinculação de tokens.
Gerir certificados de forma segura
- Armazene de forma segura: Utilize Azure Key Vault ou armazenamentos de certificados seguros
- Rodar regularmente: Implementar procedimentos de rotação de certificados
- Expiração do monitor: Configurar alertas para a expiração do certificado
- Restringir acesso: Limitar quem pode aceder às chaves privadas dos certificados
Ligações de rede seguras
- Exigir TLS 1.2+: Garantir que todas as ligações utilizam versões modernas de TLS
- Validar certificados: Implementar a validação adequada de certificados no servidor
- Use cifras fortes: Configure conjuntos de cifras seguras
Gerir tokens de forma segura
- Tempo de vida curto: Use tokens de curta duração (recomendado: 1 hora)
- Armazenamento adequado: Nunca logar ou expor tokens
- Valide minuciosamente: Verifique todas as declarações, a expiração e a vinculação
Siga as melhores práticas
Tenha em mente as seguintes recomendações ao implementar a ligação de tokens PoP mTLS.
- Use sempre HTTPS: o mTLS PoP requer transporte seguro
- Use um certificado que armazene o material da chave privada em hardware, por exemplo, no TPM: Use hardware em vez de segurança por software para melhor proteção
- Implementar um tratamento adequado de erros: Gerir corretamente erros de certificados e tokens
- Expiração do certificado de monitorização: Renovação automática de certificados
- Use certificados separados por ambiente: dev, staging e certificados de produção
- Eventos de segurança de registo: Rastrear falhas de ligação de tokens e incompatibilidades de certificados
- Rotação de certificados de teste: Certifique-se de que a sua aplicação lida com as atualizações de certificados
- Documente a sua configuração: Mantenha uma documentação clara dos requisitos do certificado
Conteúdo relacionado
- Documentação do Microsoft Identity Web
- Visão Geral sobre o Uso de APIs Downstream
- Documentação de APIs Personalizadas
- Microsoft Entra Credenciais de Certificado
- OAuth 2.0 Mutual-TLS Autenticação de Clientes
Explorar código de exemplo
Amostras completas e funcionais que demonstram a ligação de tokens MTLS PoP estão disponíveis no repositório:
-
Aplicação do Cliente:
tests/DevApps/MtlsPop/MtlsPopClient -
Servidor Web API:
tests/DevApps/MtlsPop/MtlsPopWebApi
Estas amostras demonstram:
- Configuração completa do cliente e servidor
- Aquisição de token com ligação de certificados
- Implementação de manipulador de autenticação personalizado
- Validação de certificados e verificação de impressão digital