Client Certificate in ASP.NET Core 3.1 web app always null
See original GitHub issueDescribe the bug
I am working on prototyping an ASP.NET Core 3.1 web application using Kestrel, hosted in Azure Kubernetes Service. One of the requirements is Client Certificate authentication. I followed the guidelines provided in this wiki, however, client certificate on server side is always retrieved as null. This usage is new to me and I apologize for any obvious missing elements which I am hoping to figure out and learn.
To Reproduce
Following is what I have in my local setup:-
Created and trusted local self signed chained client certificates for experimentation as per Create Certificates in Powershell page.
Added the following in startup.cs:-
public void ConfigureServices(IServiceCollection services)
{
services.Configure<HttpsConnectionAdapterOptions>(options =>
{
options.ClientCertificateMode = ClientCertificateMode.AllowCertificate;
options.CheckCertificateRevocation = false;
options.ClientCertificateValidation = (certificate2, chain, policyErrors) =>
{
// accept any cert (testing purposes only)
return true;
};
});
...
services.AddAuthentication(
CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
{
options.AllowedCertificateTypes = CertificateTypes.All;
});
...
}
...
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseAuthentication();
...
}
Added the following in Program.cs:-
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
...
.ConfigureKestrel(serverOptions =>
{
serverOptions.ConfigureHttpsDefaults(listenOptions =>
{
listenOptions.ClientCertificateMode = ClientCertificateMode.AllowCertificate;
// Enforcing TLS 1.2 and disabling previous TLS versions.
listenOptions.SslProtocols = SslProtocols.Tls12;
// Configuring cipher suite ordering
...
});
})
I am trying to retrieve the certificate in the middleware with following. The clientCertificate object retrieved is always null:-
using System.Security.Cryptography.X509Certificates;
using Microsoft.AspNetCore.Http;
public class AuthorizationMiddleware
{
...
public async Task InvokeAsync(HttpContext httpContext)
{
...
X509Certificate2 clientCertificate = await httpContext.Connection.GetClientCertificateAsync();
//OR
clientCertificate = httpContext.Connection.ClientCertificate;
...
}
...
}
Client test code to make the HTTPS request with client cert:-
try
{
var cert = new X509Certificate2("E:\\certs\\clientcert.pfx");
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(cert);
var client = new HttpClient(handler);
var request = new HttpRequestMessage()
{
RequestUri = new Uri("https://localhost:44322/apipattern"),
Method = HttpMethod.Get,
};
Task<HttpResponseMessage> responseTask = client.SendAsync(request);
Task.WaitAll(responseTask);
HttpResponseMessage response = responseTask.Result;
if (response.IsSuccessStatusCode)
{
Task<string> responseContentTask = response.Content.ReadAsStringAsync();
string responseContent = responseContentTask.Result;
Console.WriteLine(responseContent);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Further technical details
- ASP.NET Core version - 3.1
- Include the output of
dotnet --info
.NET Core SDK (reflecting any global.json):
Version: 3.1.100
Commit: cd82f021f4
Runtime Environment:
OS Name: ubuntu
OS Version: 18.04
OS Platform: Linux
RID: ubuntu.18.04-x64
Base Path: /home/mawagle/dotnetcore/sdk/3.1.100/
Host (useful for support):
Version: 3.1.0
Commit: 65f04fb6db
.NET Core SDKs installed:
3.1.100 [/home/mawagle/dotnetcore/sdk]
.NET Core runtimes installed:
Microsoft.AspNetCore.App 3.1.0 [/home/mawagle/dotnetcore/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 3.1.0 [/home/mawagle/dotnetcore/shared/Microsoft.NETCore.App]
To install additional .NET Core runtimes or SDKs:
https://aka.ms/dotnet-download
- The IDE (VS / VS Code/ VS4Mac) you’re running on, and it’s version - VS 2019
Issue Analytics
- State:
- Created 3 years ago
- Comments:6 (3 by maintainers)
@mawagle Sounds like this has been answered via email by @BrennanConroy. Feel free to re-open if your issue persists
Thanks a ton @BrennanConroy for the offline help. Adding the following config into the IISExpress applicationhost.config did the trick:-
Also I could get it working in Kestrel with the following config in Program.cs:-