Facing SSL certificate validation error when using .NET 5 and above framework for some http services during recording #710

Closed
opened 2025-12-29 08:32:49 +01:00 by adam · 1 comment
Owner

Originally created by @tavisca-mjadhav on GitHub (Aug 4, 2025).

Originally assigned to: @StefH on GitHub.

Describe the bug

Facing issue when connecting to the service during recording. "The SSL connection could not be established, see inner exception."

System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
 ---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
 ---> System.ComponentModel.Win32Exception (0x80090302): The function requested is not supported
   --- End of inner exception stack trace ---
   at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken)
   at System.Net.Security.SslStream.ProcessAuthenticationWithTelemetryAsync(Boolean isAsync, CancellationToken cancellationToken)
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(QueueItem queueItem)
   at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.HttpConnectionWaiter`1.WaitForConnectionWithTelemetryAsync(HttpRequestMessage request, HttpConnectionPool pool, Boolean async, CancellationToken requestCancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.DecompressionHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)

Expected behavior:

Should successfully connect to the service and perform the recording.

Test to reproduce

  • 1
[Fact]
public async Task GivenConfiguration_WhenRecording_ThenShouldRecord1()
{
   // Assign

   var client = HttpClientFactory2.Build(new ProxyAndRecordSettings());

   // Act
   var requestMessage = new HttpRequestMessage
   {
       Method = HttpMethod.Get,
       RequestUri = new Uri("https://dh480.badssl.com/"),
   };

   try
   {
       var response = await client.SendAsync(requestMessage);
   }
   catch (Exception ex)
   {
   }

   // Assert

}

Since in .net 5 and above the SocketsHttpHandler has been introduced, the HttpClientHandler ServerCertificateCustomValidationCallback is not being considered when TLS1.3 is enforced.

Please check this for the fix that can be applied.

https://github.com/tavisca-mjadhav/WireMock.Net/blob/SSL-ISSUE-FIX/src/WireMock.Net.Minimal/Http/HttpClientBuilder.cs

OR enabling TLS13 will work.

using System.Net;
using System.Net.Http;
using WireMock.HttpsCertificate;
using WireMock.Settings;

namespace WireMock.Http;

internal static class HttpClientBuilder
{
    public static HttpClient Build(HttpClientSettings settings)
    {
#if NETSTANDARD || NETCOREAPP3_1 || NET5_0_OR_GREATER
        var handler = new HttpClientHandler
        {
            CheckCertificateRevocationList = false,
            SslProtocols = System.Security.Authentication.SslProtocols.Tls13 | System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls,
            ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true,
            AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
        };
#elif NET46
        var handler = new HttpClientHandler
        {
            ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true,
            AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
        };
#else
        var handler = new WebRequestHandler
        {
            ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true,
            AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
        };
#endif

        if (!string.IsNullOrEmpty(settings.ClientX509Certificate2ThumbprintOrSubjectName))
        {
            handler.ClientCertificateOptions = ClientCertificateOption.Manual;

            var x509Certificate2 = CertificateLoader.LoadCertificate(settings.ClientX509Certificate2ThumbprintOrSubjectName!);
            handler.ClientCertificates.Add(x509Certificate2);
        }
        else if (settings.Certificate != null)
        {
            handler.ClientCertificateOptions = ClientCertificateOption.Manual;
            handler.ClientCertificates.Add(settings.Certificate);
        }

        handler.AllowAutoRedirect = settings.AllowAutoRedirect == true;

        // If UseCookies enabled, httpClient ignores Cookie header
        handler.UseCookies = false;

        if (settings.WebProxySettings != null)
        {
            handler.UseProxy = true;

            handler.Proxy = new WebProxy(settings.WebProxySettings.Address);
            if (settings.WebProxySettings.UserName != null && settings.WebProxySettings.Password != null)
            {
                handler.Proxy.Credentials = new NetworkCredential(settings.WebProxySettings.UserName, settings.WebProxySettings.Password);
            }
        }

#if !NETSTANDARD1_3
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
        ServicePointManager.ServerCertificateValidationCallback = (message, cert, chain, errors) => true;
#endif

        return HttpClientFactory2.Create(handler);
    }
}
Originally created by @tavisca-mjadhav on GitHub (Aug 4, 2025). Originally assigned to: @StefH on GitHub. ### Describe the bug Facing issue when connecting to the service during recording. "The SSL connection could not be established, see inner exception." ``` System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception. ---> System.ComponentModel.Win32Exception (0x80090302): The function requested is not supported --- End of inner exception stack trace --- at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken) at System.Net.Security.SslStream.ProcessAuthenticationWithTelemetryAsync(Boolean isAsync, CancellationToken cancellationToken) at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken) --- End of inner exception stack trace --- at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(QueueItem queueItem) at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.HttpConnectionWaiter`1.WaitForConnectionWithTelemetryAsync(HttpRequestMessage request, HttpConnectionPool pool, Boolean async, CancellationToken requestCancellationToken) at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken) at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.DecompressionHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken) ``` ### Expected behavior: Should successfully connect to the service and perform the recording. ### Test to reproduce - 1 ``` c# [Fact] public async Task GivenConfiguration_WhenRecording_ThenShouldRecord1() { // Assign var client = HttpClientFactory2.Build(new ProxyAndRecordSettings()); // Act var requestMessage = new HttpRequestMessage { Method = HttpMethod.Get, RequestUri = new Uri("https://dh480.badssl.com/"), }; try { var response = await client.SendAsync(requestMessage); } catch (Exception ex) { } // Assert } ``` ### Other related info Since in .net 5 and above the SocketsHttpHandler has been introduced, the HttpClientHandler ServerCertificateCustomValidationCallback is not being considered when TLS1.3 is enforced. Please check this for the fix that can be applied. https://github.com/tavisca-mjadhav/WireMock.Net/blob/SSL-ISSUE-FIX/src/WireMock.Net.Minimal/Http/HttpClientBuilder.cs **OR enabling TLS13 will work.** ``` c# using System.Net; using System.Net.Http; using WireMock.HttpsCertificate; using WireMock.Settings; namespace WireMock.Http; internal static class HttpClientBuilder { public static HttpClient Build(HttpClientSettings settings) { #if NETSTANDARD || NETCOREAPP3_1 || NET5_0_OR_GREATER var handler = new HttpClientHandler { CheckCertificateRevocationList = false, SslProtocols = System.Security.Authentication.SslProtocols.Tls13 | System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls, ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true, AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }; #elif NET46 var handler = new HttpClientHandler { ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true, AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }; #else var handler = new WebRequestHandler { ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true, AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }; #endif if (!string.IsNullOrEmpty(settings.ClientX509Certificate2ThumbprintOrSubjectName)) { handler.ClientCertificateOptions = ClientCertificateOption.Manual; var x509Certificate2 = CertificateLoader.LoadCertificate(settings.ClientX509Certificate2ThumbprintOrSubjectName!); handler.ClientCertificates.Add(x509Certificate2); } else if (settings.Certificate != null) { handler.ClientCertificateOptions = ClientCertificateOption.Manual; handler.ClientCertificates.Add(settings.Certificate); } handler.AllowAutoRedirect = settings.AllowAutoRedirect == true; // If UseCookies enabled, httpClient ignores Cookie header handler.UseCookies = false; if (settings.WebProxySettings != null) { handler.UseProxy = true; handler.Proxy = new WebProxy(settings.WebProxySettings.Address); if (settings.WebProxySettings.UserName != null && settings.WebProxySettings.Password != null) { handler.Proxy.Credentials = new NetworkCredential(settings.WebProxySettings.UserName, settings.WebProxySettings.Password); } } #if !NETSTANDARD1_3 ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; ServicePointManager.ServerCertificateValidationCallback = (message, cert, chain, errors) => true; #endif return HttpClientFactory2.Create(handler); } } ```
adam added the bug label 2025-12-29 08:32:49 +01:00
adam closed this issue 2025-12-29 08:32:49 +01:00
Author
Owner

@StefH commented on GitHub (Oct 5, 2025):

https://github.com/wiremock/WireMock.Net/pull/1363

@StefH commented on GitHub (Oct 5, 2025): https://github.com/wiremock/WireMock.Net/pull/1363
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/WireMock.Net#710