Version 5.x has been out of support since December 13, 2022, and this corresponding section of the documentation is no longer maintained. We strongly recommend upgrading to a supported version.
Clients can use an X.509 client certificate as an authentication mechanism to endpoints in your IdentityServer.
For this you need to associate a client certificate with a client in your IdentityServer and enable MTLS support on the options.
var builder = service.AddIdentityServer(options =>
{
options.MutualTls.Enabled = true;
})
Use the DI extensions methods to add the services to DI which contain a default implementation to do that either thumbprint or common-name based:
builder.AddMutualTlsSecretValidators();
Then add client secret of type SecretTypes.X509CertificateName (for PKI-based scenarios) or SecretTypes.X509CertificateThumbprint (for self-issued certificates) to the client you want to authenticate.
For example::
new Client
{
ClientId = "mtls.client",
AllowedGrantTypes = GrantTypes.ClientCredentials,
AllowedScopes = { "api1" },
ClientSecrets =
{
// name based
new Secret(@"CN=client, OU=production, O=company", "client.dn")
{
Type = SecretTypes.X509CertificateName
},
// or thumbprint based
new Secret("bca0d040847f843c5ee0fa6eb494837470155868", "mtls.tb")
{
Type = SecretTypes.X509CertificateThumbprint
},
}
}
When writing a client to connect to IdentityServer, the SocketsHttpHandler (or HttpClientHandler depending on you .NET version) class provides a convenient mechanism to add a client certificate to outgoing requests.
Use such a handler with HttpClient to perform the client certificate authentication handshake at the TLS channel. The following snippet is using IdentityModel to read the discovery document and request a token:
static async Task<TokenResponse> RequestTokenAsync()
{
var handler = new SocketsHttpHandler();
var cert = new X509Certificate2("client.p12", "password");
handler.SslOptions.ClientCertificates = new X509CertificateCollection { cert };
var client = new HttpClient(handler);
var disco = await client.GetDiscoveryDocumentAsync(Constants.Authority);
if (disco.IsError) throw new Exception(disco.Error);
var response = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
Address = disco.MtlEndpointAliases.TokenEndpoint
ClientId = "mtls.client",
Scope = "api1"
});
if (response.IsError) throw new Exception(response.Error);
return response;
}
TODO: add ASP.NET Core client sample