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 you upgrade to the latest supported version of 7.x and read the latest version of this documentation.
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