Search code examples
c#azure-web-app-servicerestsharp

RestSharpv107, ClientCertificate authentication broken in Azure. The request was aborted: Could not create SSL/TLS secure channel


I am using client certificate authentication for accessing a third party API. It was working fine till RestSharp 106.

When upgraded to v107/108, certificate authentication broke after deploying the app to Azure App Service. The application is working well on dev machines.

Following error appears -

HttpStatusCode: 0 (0) System.Web.HttpException (0x80004005): Error while calling API ---> System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel. at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult) at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar) 

My code for attaching certificate is (certificate is stored as base64 in settings)-

var x509 = new X509Certificate2();
x509.Import(certificateBytes, certificatePassword, X509KeyStorageFlags.DefaultKeySet);
certificateCollection = new X509Certificate2Collection { x509 };

var options = new RestClientOptions(new Uri(serverBaseUrl))
            {
                MaxTimeout = (int)TimeSpan.FromMinutes(5).TotalMilliseconds,
            };

if (certificateCollection != null)
{
    options.ClientCertificates = certificateCollection;
}

var client = new RestClient(options);

What I have checked till now -

Correct API is being called. (logged using HttpTracer) Correct Certificate is being used. (logged before API call from client. -

client.Options.ClientCertificates[0]

Any help is appreciated.

Update :

Tried Kevin's solution on KUDU using powershell, here is my code.

$Cert = new-object security.cryptography.x509certificates.x509certificate2
$cacertstr='base64stringofcertificate'
$bytes =[System.Convert]::FromBase64String($certstr)
$cert.Import($bytes,'certpassword',[System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::DefaultKeySet)
$collection = New-Object security.cryptography.x509certificates.X509Certificate2Collection($cert)
$bytes =    [System.Convert]::FromBase64String($cacertstr)
$cert.Import($bytes)
$collection.Add($cert);
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("header1", "value1")
$headers.Add("header2", "value2")
$response = Invoke-RestMethod 'https://url' -Method 'GET' -Headers $headers -Certificate $cert

Same error

Invoke-RestMethod : The request was aborted: Could not create SSL/TLS > secure channel.


Solution

  • We had the same issue, and the same error message, but with RestSharp version 106...

    Could not create SSL/TLS secure channel

    We then tried with a pure HttpClient the same error occurred, which excluded a problem with RestSharp itself.

    After months of investigations, including packets captures from Azure, we discovered that our requests were not even going out from the Azure infrastructure. HELLO packets were not found in our traces, proving nothing was getting out from Azure.

    We contacted Azure's support team and found out what was the problem: In Azure, all requests carrying an attached TLS certificate are BLOCKED by default.

    You need to add a property in your App Service settings, WEBSITE_LOAD_CERTIFICATES which specifies which TLS thumbprints you allow! Mind you, this is effective for outgoing requests as well! And even for certificates you manage yourself without using any of Azure certificates feature thing!

    This is absolute nonsense! I am right now arguing with the poor support guy that this is a backward behavior from Azure. My expectation as a Azure user, is that nothing should be blocked by default unless I do make some settings change myself! Especially not outgoing requests! Anyway.

    All of this is documented there: https://learn.microsoft.com/en-us/azure/app-service/configure-ssl-certificate-in-code#make-the-certificate-accessible

    Adding a new property WEBSITE_LOAD_CERTIFICATES=* solved our issue. RestSharp or HttpClient both worked fine in the end.