dotnet / dotnet/aspnetcore

How to accept a client certificate signed by an untrusted CA in Asp .netcore?

Open
#48,099 18 comments 0 reactions 0 assignees View on GitHub
area-auth enhancement
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 5h
Merged PRs (30d)
276

Description

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Describe the bug

I have created a client and a server application to demonstrate Mutual TLS (mTLS). I generated a client certificate and had it signed by a local CA. However, the CA is not trusted by the server. I want to bypass any certificate validation on the server.

I can confirm that the server has received the client certificate, but the
OnAuthenticationFailed is fired and the attached exception is Client certificate failed validation.

Upon debugging, I found that it is CertificateAuthenticationHandler (source code [here](https://github.com/dotnet/aspnetcore/blob/main/src/Security/Authentication/Certificate/src/CertificateAuthenticationHandler.cs)) that rejects the certificate. Also, I think it is due the failed certificate chain validation ([here](https://github.com/dotnet/aspnetcore/blob/main/src/Security/Authentication/Certificate/src/CertificateAuthenticationHandler.cs#L143)).

### Expected Behavior

`AllowAnyClientCertificate` disables further validation a client certificate.

### Steps To Reproduce

```csharp
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);

builder.Services.Configure(options =>
{
options.ConfigureHttpsDefaults(options =>
{
options.AllowAnyClientCertificate();
options.CheckCertificateRevocation = false;
options.ClientCertificateValidation = ClientCertificateValidation;
options.ClientCertificateMode = ClientCertificateMode.AllowCertificate;
});
});

// Add services to the container.

builder.Services.AddControllers();

ConfigureServices(builder.Services);

var app = builder.Build();

// Configure the HTTP request pipeline.

app.UseHttpsRedirection();

app.UseAuthentication();

app.MapControllers();

app.Run();
}

private static bool ClientCertificateValidation(X509Certificate2 arg1, X509Chain? arg2, SslPolicyErrors arg3)
{
return true;
}

private static void ConfigureServices(IServiceCollection services)
{
services
.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
{
options.RevocationMode = X509RevocationMode.NoCheck;
options.ChainTrustValidationMode = X509ChainTrustMode.CustomRootTrust;
options.AllowedCertificateTypes = CertificateTypes.All;
options.ValidateCertificateUse = false;
options.ValidateValidityPeriod = false;

options.Events = new CertificateAuthenticationEvents
{
OnAuthenticationFailed = p =>
{
Console.WriteLine(p.Exception);
return Task.CompletedTask;

},
OnCertificateValidated = context =>
{
// Add certificate to HttpContext.Items
context.HttpContext.Items["ClientCertificate"] = context.ClientCertificate;
return Task.CompletedTask;
}
};
});
}
}
```

### Exceptions (if any)

_No response_

### .NET Version

7.0.100

### Anything else?

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.