How to add a client certificate in a SocketsHttpHandler?
See original GitHub issueIs 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:
- Created 5 months ago
- Comments:14 (10 by maintainers)
Well, finally I could add the certificate to the socket in this way:
The certificate is received by the server, that can be validate if it is needed, for mutual authentication, for example.
@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.