.NET Core | Kestrel with client certificate authentication

Introduction
I’ll start this article with a very simple statement:
I intend to explain the subject in the simplest and quickest way possible.
If you are interested in exploring the subject further, please visit Microsoft Official site.
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel?view=aspnetcore-3.1
Kestrel is a cross-platform web server for ASP.NET Core.
Kestrel is supported on all platforms and versions that .NET Core supports.
Kestrel in ASP.NET Core apps
Create new .net core web application empty project in visual studio.
How to Configure Https Defaults -
Open program.cs and use ConfigureKestrel —
.ConfigureKestrel(options =>
{
options.ConfigureHttpsDefaults(o =>
{
// certificate is an X509Certificate2
o.ServerCertificate = cert;
o.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
});
}).UseUrls($"https://*:{int.Parse(Configuration["Port"])}")
- Load cert as embed resource and store the *.pfx password as encrypted (Salted password hashing in C#).
- UseUrls allow you to specify the urls the web host will listen on.
How to Authentication with client certificate-
- Open startup.cs and add services.AddAuthentication
services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
{
options.AllowedCertificateTypes = CertificateTypes.All;
options.Events = new CertificateAuthenticationEvents
{
OnCertificateValidated = context =>
{
var validationService = context.HttpContext.RequestServices.GetService<ICertificateValdiaor>();
if(validationService.ValidateCertificate(context.ClientCertificate))
{
context.Success();
}
else
{
context.Fail("Invalid certifcate supplied");
}
return Task.CompletedTask;
}
};
});
- ValidatonService is an implementation ICertificateValdiaor —
public bool ValidateCertificate(X509Certificate2 clientCertificate);
My implementation is compare between my certificate Thumbprint and client thumbprint , (you can add more validations if necessary).
public bool ValidateCertificate(X509Certificate2 clientCertificate)
{
try
{
bool result = false;
var cert = _resourcesManager.GetCertificateFromResource();
if (cert != null && clientCertificate.Thumbprint == cert.Thumbprint)
{
result = true;
}
return result;
}
catch (Exception ex)
{
_log.Error($"Failed to validate certificate {ex}");
throw ex;
}
}
Deploy (e.g. — Windows service) —
Go back to program.cs and modify Run() to
#if DEBUG
Run();
#else
RunAsService();
#endif
RunAsService is from another namespace-
Microsoft.AspNetCore.Hosting.WindowsServices