question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to add a client certificate in a SocketsHttpHandler?

See original GitHub issue

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

I have a client gRPC service, and i would like to implement mTLS, so I would like to add the client certificate to the gRPC channel.

To create the gRPC channel, I am using this code:

X509Certificate2 miCertificadoCliente = X509Certificate2.CreateFromPem(paramStrCertificadoCliente);


SslClientAuthenticationOptions misOpcionesDeAutenticacion = new SslClientAuthenticationOptions();
misOpcionesDeAutenticacion.RemoteCertificateValidationCallback = ValidateServerCertificate;
misOpcionesDeAutenticacion.ClientCertificates = new X509CertificateCollection();
misOpcionesDeAutenticacion.ClientCertificates.Add(miCertificadoCliente);

SocketsHttpHandler miHttpHandler = new SocketsHttpHandler();
miHttpHandler.SslOptions = misOpcionesDeAutenticacion;


HttpClient httpClient = new HttpClient(miHttpHandler);

GrpcChannelOptions misOpcionesDelCanal = new GrpcChannelOptions()
{
    MaxReceiveMessageSize = 62914560,
    MaxSendMessageSize = 62914560,
    HttpClient = httpClient,
};



CallCredentials misCredencialesDeLlamada = CallCredentials.FromInterceptor((c, m) =>
{
    m.Add(HeaderNames.Authorization, $"Bearer {_tokenJwt}");
    return Task.CompletedTask;
});


var misCredencialesdelCanal = ChannelCredentials.Create(new SslCredentials(), misCredencialesDeLlamada);

misOpcionesDelCanal.Credentials = myChannelCredentials;


GrpcChannel miCanalGrpc = GrpcChannel.ForAddress("https://localhost:5001", misOpcionesDelCanal);

Btu the problem is that when the client makes a request to the server, I get an error in the handshake because the server requieres a client certificate, but it seems that the client add correctly the certificate.

If I configure the server to don’t need client certificate, the server replies to the client.

So I guess the problem is that I am not adding the certificate in the correct way. How should I do it?

Thanks.

EDIT 01:

I have tried with this code (from documentation: https://learn.microsoft.com/en-us/dotnet/architecture/grpc-for-wcf-developers/channel-credentials):

X509Certificate2 cert = X509Certificate2.CreateFromPem(paramStrCertificadoCliente, paramStrKeyCliente);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
    var originalCert = cert;
    cert = new X509Certificate2(cert.Export(X509ContentType.Pkcs12));
    originalCert.Dispose();
}


var handler = new HttpClientHandler();
handler.ClientCertificates.Add(cert);

var httpClient = new HttpClient(handler);


var callCredentials = CallCredentials.FromInterceptor(((context, metadata) =>
{
    metadata.Add("Authorization", $"Bearer {_tokenJwt}");
    return Task.CompletedTask;
}));

var channelCredentials = ChannelCredentials.Create(new SslCredentials(), callCredentials);

var channel = GrpcChannel.ForAddress("https://localhost:5002/", new GrpcChannelOptions
{
    HttpClient = httpClient,
    Credentials = channelCredentials
});

Perhaps the problem is that I want to use a self signed certificate that is not isntalled in the certificates store, but I don’t want to have to install it, I would like to can use the certificate provided as a local file.

Issue Analytics

  • State:closed
  • Created 5 months ago
  • Comments:14 (10 by maintainers)

github_iconTop GitHub Comments

1reaction
ComptonAlvarocommented, May 4, 2023

Well, finally I could add the certificate to the socket in this way:

//Craete the certificate from the PEM files
X509Certificate2 miCertificadoCliente = X509Certificate2.CreateFromPem(paramStrCertificadoCliente, paramStrKeyCliente);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
    var originalCert = miCertificadoCliente;
    miCertificadoCliente = new X509Certificate2(miCertificadoCliente.Export(X509ContentType.Pkcs12));
    originalCert.Dispose();
}


//Create the authentication options for the socket
SslClientAuthenticationOptions misOpcionesDeAutenticacion = new SslClientAuthenticationOptions();
misOpcionesDeAutenticacion.RemoteCertificateValidationCallback = ValidarCertificadoServidor;
misOpcionesDeAutenticacion.ClientCertificates = new X509CertificateCollection();
misOpcionesDeAutenticacion.ClientCertificates!.Add(miCertificadoCliente);


//Create the socket and assign the authentication options.
SocketsHttpHandler miHttpHandler = new SocketsHttpHandler();
miHttpHandler.SslOptions = misOpcionesDeAutenticacion;

The certificate is received by the server, that can be validate if it is needed, for mutual authentication, for example.

1reaction
amcaseycommented, May 2, 2023

@ComptonAlvaro In the future, it might be clearer to create a standalone repo or gist containing your code so you don’t have to paste it over and over and you can modify it as you apply various suggestions.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Net Core SocketsHttpHandler with Client Certificates ...
We're using certs from azure key vault. I'm not sure what it does to the certs, but it seems to cause the httpclient...
Read more >
Using SocketsHttpHandler in .NET Core 2.2 and ignoring ...
@djsoteric I had the same exact issue, solved it this way public static HttpClient CreateHttpClient() { var sslOptions = new ...
Read more >
SocketsHttpHandler.SslOptions Property (System.Net.Http)
Gets or sets the set of options used for client TLS authentication. public: property System::Net::Security::SslClientAuthenticationOptions ^ SslOptions ...
Read more >
HTTP Client Configuration
Custom data can be provided in the cluster metadata. This example shows adding a client certificate that will authenticate the proxy to the...
Read more >
Using Certificate Authentication with IHttpClientFactory and ...
This article shows how an HttpClient instance could be setup to send a certificate to an API to use for certificate authentication.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found