Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Observera
Alla klienter kan inte hämta mTLS PoP-certifikat eftersom den här funktionen för närvarande är i privat förhandsversion.
Certifikattokenbindning (även kallat mTLS PoP – Mutual TLS Proof-of-Possession) är en avancerad säkerhetsfunktion som kryptografiskt binder åtkomsttoken till ett specifikt X.509-certifikat. RFC 8705 beskriver den här bindningen. Bindningen säkerställer att även om en token fångas upp kan en angripare inte använda den utan innehav av motsvarande privata nyckel.
Förstå hur tokenbindning fungerar
Följande steg beskriver tokenbindningsflödet från förvärv via verifiering.
- Token Acquisition: När du begär en åtkomsttoken med tokenbindning aktiverat innehåller Microsoft Identity Web certifikatets tumavtryck i tokenbegäran
-
Tokenbindning: Auktoriseringsservern bäddar in ett
cnf(bekräftelse)-anspråk i den utfärdade token som innehåller certifikatets SHA-256 tumavtryck (x5t#S256) - API-anrop: Klienten presenterar både den bundna token och certifikatet när den anropar det underordnade API:et
-
Verifiering: API:et verifierar att certifikatet som visas matchar certifikatreferensen i tokens
cnfanspråk
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
Granska säkerhetsfördelar
Tokenbindning ger följande fördelar för att skydda dina program.
- Skydd mot tokenstöld: Stulna token är värdelösa utan motsvarande certifikat
- Skydd mot reprisattacker: Token kan inte spelas upp från olika klienter
- Förbättrad autentisering: Kombinerar "något du har" (certifikat) med traditionella OAuth2-flöden
- Nulová dôvera (Zero Trust) Architecture: Överensstämmer med zero trust principer genom att binda autentiseringsuppgifter till specifika enheter
Konfigurera tokenbindning
Konfigurera både klientprogrammet och API-servern för att aktivera mTLS PoP-tokenbindning.
Konfigurera klientprogrammet
Utför följande steg för att konfigurera klientprogrammet för tokenbindning.
1. Konfigurera inställningar för Microsoft Entra ID
I din appsettings.json konfigurerar du dina Microsoft Entra inställningar, inklusive certifikatet:
{
"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. Konfigurera underordnat API med tokenbindning
Konfigurera ditt underordnade API-avsnitt med MTLS_POP protokollschemat:
{
"DownstreamApi": {
"BaseUrl": "https://api.contoso.com/",
"RelativePath": "api/data",
"ProtocolScheme": "MTLS_POP",
"RequestAppToken": true,
"Scopes": [ "api://your-api-scope/.default" ]
}
}
Viktiga konfigurationsegenskaper:
-
ProtocolScheme: Måste anges till"MTLS_POP"för att aktivera tokenbindning -
RequestAppToken: Måste varatrue(tokenbindning stöder för närvarande endast programtoken) -
Scopes: API-omfång som krävs för det underordnade API-anropet
3. Registrera tjänster
Registrera den underordnade API-tjänsten i programmets startkod. I följande exempel visas både konsolapp och ASP.NET Core metoder.
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"));
Konfigurera API-servern
Det underordnade API:et måste verifiera både token- och certifikatbindningen. Här är ett fullständigt exempel:
1. Registrera autentiseringshanterare
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. Implementera mTLS PoP-autentiseringshanterare
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);
}
}
Använda tokenbindning i program
I följande exempel visas hur du integrerar mTLS PoP-tokenbindning i olika programtyper.
Anropa API:er från en konsol eller ett daemonprogram
I följande exempel visas en konsol eller ett daemonprogram som anropar ett underordnat API med mTLS PoP-tokenbindning.
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; }
}
Anropa API:er från en ASP.NET Core webbapp
I följande exempel visas en kontrollant som anropar ett underordnat API med mTLS PoP-tokenbindning.
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; }
}
Konfigurera DownstreamApiOptions programmatiskt
I följande exempel anges mTLS PoP-alternativ direkt i kod i stället för konfigurationsfiler.
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" };
});
}
}
Använda MicrosoftIdentityMessageHandler med tokenbindning
MicrosoftIdentityMessageHandler stöder mTLS PoP-tokenbindning via tilläggsmetoderna AddMicrosoftIdentityMessageHandler . När ProtocolScheme är inställt på "MTLS_POP"hämtar hanteraren automatiskt en bunden token och skickar begäranden via en mTLS-konfigurerad HTTP-klient.
Konfigurera infogade alternativ
I följande exempel registreras en HTTP-klient med infogad mTLS PoP-konfiguration och dess användning i en tjänst.
// 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();
}
}
Läs in konfiguration från appsettings.json
Du kan också läsa in tokenbindningsinställningar från konfigurationsfilen.
appsettings.json:
{
"DownstreamApis": {
"SecureApi": {
"Scopes": ["api://secure-api/.default"],
"ProtocolScheme": "MTLS_POP",
"RequestAppToken": true
}
}
}
Program.cs: Följande kod registrerar HTTP-klienten med hjälp av konfigurationsavsnittet.
services.AddHttpClient("SecureApiClient", client =>
{
client.BaseAddress = new Uri("https://secure-api.example.com");
})
.AddMicrosoftIdentityMessageHandler(
configuration.GetSection("DownstreamApis:SecureApi"),
"SecureApi");
Tillämpa tokenbindning för varje begäran
Använd alternativ per begäran när vissa begäranden behöver tokenbindning och andra inte:
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();
}
Mer information om finns i dokumentationen om MicrosoftIdentityMessageHandleranpassade API:er.
Skapa en anpassad HttpClient med auktoriseringshuvudprovider
Använd den här metoden för scenarier som kräver mer kontroll över HTTP-begäranden. I följande exempel hämtas ett bundet auktoriseringshuvud och en mTLS-konfigurerad HTTP-klient skapas.
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);
}
}
Granska tokenstrukturen
I följande exempel visas hur standard- och bundna token skiljer sig åt.
Jämföra OAuth2-standardtoken
En OAuth2-standardtoken innehåller ingen information om certifikatbindning.
{
"aud": "api://your-api",
"iss": "https://login.microsoftonline.com/tenant-id/",
"iat": 1234567890,
"exp": 1234571490,
"appid": "client-id",
"tid": "tenant-id"
}
Granska mTLS PoP-token med bindning
En mTLS PoP-token innehåller anspråket cnf som binder token till ett specifikt certifikat.
{
"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"
}
}
Anspråket cnf (bekräftelse) innehåller SHA-256-tumavtrycket för certifikatet, Base64Url-encoded.
Förstå aktuella begränsningar
Granska följande begränsningar innan du implementerar mTLS PoP-tokenbindning.
Endast stöd för programtoken
Tokenbindning stöder för närvarande endast programtoken (endast app). Delegerade (användar)token stöds inte.
Ange protokollschemat
Egenskapen ProtocolScheme måste uttryckligen anges för att aktivera tokenbindning och sättas till "MTLS_POP". Om den inte har angetts används standard Bearer-autentisering.
Uppfylla certifikatkraven
- Certifikatet måste konfigureras i
ClientCredentialsmedSendX5cinställt påtrue - Certifikatet måste vara tillgängligt vid anskaffning av token
Felsökning av vanliga problem
Använd följande vägledning för att diagnostisera och lösa problem med tokenbindning.
Lösa vanliga problem
1. "Saknade 'cnf'-anspråk i token"
Orsak: Tokenbindningen har inte konfigurerats korrekt eller så är token en standard-Bearer-token.
Lösning: Kontrollera att ProtocolScheme är inställt på "MTLS_POP" och RequestAppToken är true.
{
"DownstreamApi": {
"ProtocolScheme": "MTLS_POP", // ensure this is set
"RequestAppToken": true
}
}
2. "Felmatchning av tumavtryck för certifikat"
Orsak: Certifikatet som visas för API:et matchar inte det som används för tokenförvärv.
Lösning:
- Kontrollera att samma certifikat används för både tokenförvärv och API-anrop
- Kontrollera konfigurationen för certifikatinläsning i
ClientCredentials - Kontrollera att certifikatet inte har upphört att gälla eller förnyats
3. "Ett certifikat som krävs för tokenbindning saknas"
Cause: Inget certifikat har konfigurerats i Microsoft Entra inställningar.
Lösning: Lägg till ett certifikat i konfigurationen ClientCredentials och ange SendX5c till true.
{
"AzureAd": {
"ClientCredentials": [
{
"SourceType": "StoreWithDistinguishedName",
"CertificateStorePath": "CurrentUser/My",
"CertificateDistinguishedName": "CN=YourCertificate"
}
],
"SendX5c": true // required for token binding
}
}
4. "Tokenbindning kräver aktiverat anskaffning av apptoken"
Orsak: RequestAppToken är inte inställt på true.
Lösning: Ange RequestAppToken till true i dina alternativ.
var options = new DownstreamApiOptions
{
ProtocolScheme = "MTLS_POP",
RequestAppToken = true, // must be true
};
Felsöka tokenbindning
Använd följande tekniker för att undersöka problem med tokenbindning.
Aktivera detaljerad loggning
Lägg till följande konfiguration för att aktivera loggning på felsökningsnivå för Microsoft. Identity.Web.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Identity.Web": "Debug"
}
}
}
Granska token-krav
Använd följande kod för att lista alla anspråk i en token och söka efter anspråket 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");
Verifiera certifikatets tumavtryck
Använd följande kod för att beräkna och visa ett certifikats SHA-256 tumavtryck som jämförelse.
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}");
Följ säkerhetsriktlinjerna
Tillämpa följande säkerhetsmetoder när du implementerar tokenbindning.
Hantera certifikat på ett säkert sätt
- Arkiv på ett säkert sätt: Använd Azure Key Vault eller säkra certifikatarkiv
- Rotera regelbundet: Implementera procedurer för certifikatrotation
- Övervaka förfallodatum: Konfigurera aviseringar för certifikatets giltighetstid
- Begränsa åtkomst: Begränsa vem som kan komma åt privata certifikatnycklar
Säkra nätverksanslutningar
- Kräv TLS 1.2+: Kontrollera att alla anslutningar använder moderna TLS-versioner
- Verifiera certifikat: Implementera korrekt certifikatverifiering på servern
- Använd starka chiffer: Konfigurera säkra chiffersviter
Hantera token på ett säkert sätt
- Kort livslängd: Använd kortlivade token (rekommenderas: 1 timme)
- Rätt lagring: Registrera eller exponera aldrig tokens
- Verifiera noggrant: Kontrollera alla anspråk, förfallodatum och bindningar
Följ metodtipsen
Tänk på följande rekommendationer när du distribuerar mTLS PoP-tokenbindning.
- Använd alltid HTTPS: mTLS PoP kräver säker transport
- Använd ett certifikat som lagrar det privata nyckelmaterialet i maskinvara, t.ex. i TPM: Använd maskinvara över programvarusäkerhet för bättre skydd
- Implementera korrekt felhantering: Hantera certifikat- och tokenfel korrekt
- Övervaka certifikatets giltighetstid: Automatisera certifikatförnyelse
- Använda separata certifikat per miljö: Utvecklings-, mellanlagrings- och produktionscertifikat
- Loggsäkerhetshändelser: Spåra tokenbindningsfel och felmatchade certifikat
- Testcertifikatrotation: Kontrollera att programmet hanterar certifikatuppdateringar
- Dokumentera konfigurationen: Behåll tydlig dokumentation om certifikatkrav
Relaterat innehåll
- Microsoft Identitetswebbdokumentation
- Översikt över anropande underordnade API:er
- Dokumentation om anpassade API:er
- Microsoft Entra certifikatautentiseringsuppgifter
- OAuth 2.0 Mutual-TLS klientautentisering
Utforska exempelkod
Fullständiga arbetsexempel som visar mTLS PoP-tokenbindning är tillgängliga på lagringsplatsen:
-
Klientprogram:
tests/DevApps/MtlsPop/MtlsPopClient -
Webb-API-server:
tests/DevApps/MtlsPop/MtlsPopWebApi
Dessa exempel visar:
- Slutför klient- och serverkonfigurationen
- Tokenförvärv med certifikatbindning
- Implementering av anpassad autentiseringshanterare
- Verifiering av certifikat och tumavtryck