1

I have a token request that works on Postman on a server.

No body, just basic authentication with username and password:

enter image description here

However, I have this code below that returns the error:

The request was aborted: Could not create SSL/TLS secure channel.

Here is the code below:

string responsedata = string.Empty;

String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
                                
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlToken);                
request.Method = "POST";
request.Headers.Add("Authorization", "Basic " + encoded);
request.PreAuthenticate = true;

HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
    responsedata = reader.ReadToEnd();
}

What am I doing worng?

Kinyanjui Kamau
  • 1,890
  • 10
  • 55
  • 95
  • Before you get too far using `WebRequest`, please take a look at [the remarks for that class](https://learn.microsoft.com/en-us/dotnet/api/system.net.webrequest?view=net-7.0#remarks): *Don't use WebRequest or its derived classes for new development. Instead, use the System.Net.Http.HttpClient class.* – Xerillio Nov 27 '22 at 10:03
  • Did you check [this answer](https://stackoverflow.com/a/32995825/3034273)? – Xerillio Nov 27 '22 at 10:16
  • @Xerillio, yes I did. – Kinyanjui Kamau Nov 27 '22 at 10:19
  • Are you running the Postman code on same machine as the c#? TLS is performed before the HTTP request is sent when the URL is HTTPS (not HTTP). When TLS fails no HTTP request is sent. So the code posted has nothing to do with the failure. The ServicePointManager.SecurityProtocol should only contain TLS 1.2 and 1.3. Adding other version can give error posted. You should be using Net 4.7.2 or later which uses OS for TLS instead of Net by default. Postman is working so most likely you are using an older version of Net. – jdweng Nov 27 '22 at 10:47
  • @jdweng Postman and the c# code are running on the same machine and it is a https request. .NET Framework is 4.7.2. – Kinyanjui Kamau Nov 27 '22 at 11:00
  • What type of machine? Open up the csproj and make sure Net is not being used. The default is OS. See following : https://learn.microsoft.com/en-us/dotnet/framework/network-programming/tls – jdweng Nov 27 '22 at 11:35
  • @jdweng. It is a Windows Server 2012 R2 environment. What do you mean by making sure Net is not being used in the csproj file? – Kinyanjui Kamau Nov 27 '22 at 12:04
  • The server is working properly since you can connect using Postman. It is the client side that is the issue. Is client and server both on same machine? There are a few parameters than can be used to choose either OS or Net from TLS. One of these is SslProtocols.None another is SecurityProtocolType.SystemDefault. You have to read the link to fully understand all the combinations. – jdweng Nov 27 '22 at 16:06
  • Have you tried to specify `ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;` (before any request has been initiated)? BTW, **only** `SecurityProtocolType.Tls12`, `SecurityProtocolType.Tls13` is **not supported** (only experimental in Window 10 and needs to be activated manually, available in Windows Server 2022 / Windows 11) -- Note that, even if unrelated, you also have to declare the WebResponse with an `using` statement -- Possibly, target .Net Framework 4.8, or move to .NET 6+ – Jimi Nov 27 '22 at 16:24
  • @Jimi, yup, putting that before the request. Same problem. Lemme try targeting .Net 4.8. – Kinyanjui Kamau Nov 27 '22 at 17:08
  • Note that a failed SSL transaction can be determined by the lack of required cipher suites, which Postman handles on its own (as, e.g., all WebBrowsers do). If you have the chance, try the same code in a Windows 10 environment. Windows Server 2012 R2 is very old – Jimi Nov 27 '22 at 17:34
  • @Jimi. The same code works in a Windows 10 environment no problem. – Kinyanjui Kamau Nov 27 '22 at 17:39
  • Then it's probably a missing cipher suite. Check with [IISCrypto](https://www.nartac.com/Products/IISCrypto/) (free software) what is enabled and what is available in the System that fails. You can use a transparent Proxy (as Fiddler or Wireshark) to determine what goes wrong. If the issue is caused by the Cipher Suites (as I suspect), there's not much you can do (unless you have signed up for extended support) – Jimi Nov 27 '22 at 17:43
  • @Jimi, Will check that. My thinking was that if it works in Postman, I can get it to work in code in the same environment. If this fails, would trying to make the call by using RestSharp help? – Kinyanjui Kamau Nov 27 '22 at 17:49
  • I don't know. Probably not, but trying and failing is better than missing a chance :) – Jimi Nov 27 '22 at 17:55
  • I had the same problem when tried to call k8s API (AKS) from Windows Server 2012. As @Jimi stated the problem was a missing cipher suite. To get internal logging create an [EventListener](https://developers.redhat.com/blog/2019/12/23/tracing-net-core-applications#) for `"System.Net.Http"` event source. – Artur Nov 29 '22 at 14:43
  • @Artur, how did you fix the missing cipher suites? – Kinyanjui Kamau Nov 29 '22 at 17:49
  • Unfortunately it was impossible. According to Windows Server 2012 and AKS docs they have different set of supported cipher suits (you need at least one common cipher). So the task was postponed until the upgrade. – Artur Nov 29 '22 at 18:08
  • But I suggest to check the EventListener to make sure the problem is really in cyphers. – Artur Nov 29 '22 at 18:09
  • 1
    Try registering a ServerCertificateValidationCallback delegate and inspecting the SslPolicyErrors parameter for more information. https://learn.microsoft.com/en-us/dotnet/api/system.net.servicepointmanager.servercertificatevalidationcallback?source=recommendations&view=netframework-4.7.2 https://learn.microsoft.com/en-us/dotnet/api/system.net.security.remotecertificatevalidationcallback?view=netframework-4.8 – Neil Moss Nov 30 '22 at 16:08

2 Answers2

2

I suspect your problem is related to the SecurityProtocol your application runs on. Try running this before your request.

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

The endpoint your trying to connect probably requires a higher version of Tls than what your application is providing.

The default value of this is defined by the system it runs on see: https://learn.microsoft.com/en-us/dotnet/api/system.net.securityprotocoltype?view=net-7.0#system-net-securityprotocoltype-systemdefault

So when running on an older OS this often is too low for modern API endpoints.

You can test this by enabling or disabling specific versions of TLS/SSL in Postman, look for "Protocols disabled during handshake" in the settings tab for your request.

Jostein S
  • 456
  • 7
  • Adding ServicePointManager.SecurityProtocol to the code before the request does not fix the problem. Disabling TLSv1,TLSv1.1 and TLSv1.3 in Postman will return a token. Only when I disable TLSv1.2 does it bring an error. – Kinyanjui Kamau Nov 30 '22 at 09:40
  • Just to check, the clock on your server isn't outdated by chance? Time is a factor in SSL/TLS handshaking – Jostein S Nov 30 '22 at 10:26
  • The clock is in sync, correct time. – Kinyanjui Kamau Nov 30 '22 at 11:04
  • Have you read this article? https://learn.microsoft.com/en-us/answers/questions/825110/the-request-was-aborted-could-not-create-ssltls-se-2.html?page=2&pageSize=10&sort=oldest – Jostein S Dec 01 '22 at 07:20
0

Like Neil Moss already commented above... Think you are in use of untrusted certificate on server side so try to ignore certificate validation...

request.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
moonphone
  • 23
  • 3