Httpclientfactory does not load certificates from X509store in Linux container .net 5

  .net-5, c#, docker, linux, x509certificate

I am using .net 5 to create an api which needs to be hosted as a Linux container. I have used the HttpClientFactory to create typed HttpClient which will call an external api , this external api requires client certificates to be passed in the request for which I used the HtppClientHandler with the ConfigurePrimaryHttpMessageHandler() method. The typed HtppClientHandler was created as a separate class and in the sendasync method I attached the certificates.(also tested adding the certs in the constructor of the handler)
However the certificates seem to be only passed when the application starts up but after 2 mins of inactivity when the HttpClientHandler is disposed and a new instance is created the certificates do not get passed in the request and I get the error
System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
—> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
—> Interop+OpenSsl+SslException: SSL Handshake failed with OpenSSL error – SSL_ERROR_SSL.
—> Interop+Crypto+OpenSslCryptographicException: error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
This is the Startup.cs where SwishpayService is the typed HttpsClient

services.AddTransient<SwishpayHandler>();
services.AddHttpClient<ISwishpayService, SwishpayService>()
.ConfigurePrimaryHttpMessageHandler<SwishpayService>() ;

This is the SwishpayService.cs

 public class SwishpayHandler: HttpClientHandler
    {
        private readonly IConfiguration _config;
        private readonly ILogger<SwishpayHandler> _logger;
        public SwishpayHandler(IConfiguration config, ILogger<SwishpayHandler> logger)
        {
            _config = config;
            _logger = logger;
            
        }
        protected override async Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request,
            CancellationToken cancellationToken)
        {            
            
            if (ClientCertificates == null || ClientCertificates.Count == 0)
            {
               _logger.LogInformation("Invoked SwishpayHandler");
                using (X509Store store = new X509Store(StoreName.CertificateAuthority, StoreLocation.CurrentUser, OpenFlags.ReadWrite))
                {                  
                    var certs = new X509Certificate2Collection();
                    certs.Import(Path.Combine("Certificates", _config.GetValue<string>("SwishApi:key:certificatefile")), GetCertificatePassword(), X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
                    
                    foreach (X509Certificate2 cert in certs)
                    {
                        if (cert.HasPrivateKey)
                        {
                            ClientCertificates.Add(cert);
                        }
                        else
                        {
                            store.Add(cert);
                        }
                    }
                    store.Close();
                }
            }

            return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
        }

        private string GetCertificatePassword()
        {          
            var cert_password = File.ReadAllText(_config.GetValue<string>("SWISHPAY_CERT_PWD").Trim()).Replace(Environment.NewLine, "");

            return cert_password;
        }
    }

Used the X509store solution based this post Can a .p12 file with CA certificates be used in C# without importing them to certificate store

Source: Docker Questions

LEAVE A COMMENT