Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TLS 1.2 not negotiated in .NET 4.7 without explicit ServicePointManager.SecurityProtocol call

I need to upgrade a .NET application to support a call to an API on a website that only supports TLS 1.2. From what I read, if the application is targeting 4.6 or higher then it will use TLS 1.2 by default.

To test I created a Windows Forms app that targets 4.7. Unfortunately it errors when I don't explicitly set ServicePointManager.SecurityProtocol. Here is the code:

HttpClient _client = new HttpClient();  var msg = new StringBuilder();  // If I uncomment the next line it works, but fails even with 4.7 // ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;  var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://sandbox.authorize.net");  httpWebRequest.KeepAlive = false;  try {     var httpWebResponse = (HttpWebResponse) httpWebRequest.GetResponse();      msg.AppendLine("The HTTP request Headers for the first request are: ");      foreach (var header in httpWebRequest.Headers)     {         msg.AppendLine(header.ToString());     }      ResponseTextBox.Text = msg.ToString();  } catch (Exception exception) {    ResponseTextBox.Text = exception.Message;     if (exception.InnerException != null)    {        ResponseTextBox.Text += Environment.NewLine + @"  ->" + exception.InnerException.Message;         if (exception.InnerException.InnerException != null)        {             ResponseTextBox.Text += Environment.NewLine + @"     ->" + exception.InnerException.InnerException.Message;        }    } } 

If you uncomment out the following line:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; 

it works. This isn't a good solution since it hard codes what TLS version to use, so it wouldn't use TLS 1.3 in future.

What else do I need to do to get it work without having this line. I'm testing from a Window 10 machine with 4.7 installed.

Update

I tried a test with HttpClient and had the same results, I had to explicitly set SecurityProtocol.

Code:

var msg = new StringBuilder();  // Need to uncomment code below for TLS 1.2 to be used // ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;  try {    var response = await _client.GetAsync(@"https://sandbox.authorize.net");     msg.AppendLine("response.IsSuccessStatusCode : " + response.IsSuccessStatusCode);     msg.AppendLine(await response.Content.ReadAsStringAsync());     textBox.Text = msg.ToString();   }    catch (Exception exception)   {       textBox.Text = exception.Message;        if (exception.InnerException != null)       {           textBox.Text += Environment.NewLine + @"  ->" + exception.InnerException.Message;       }    } 
like image 718
Josh Avatar asked Jun 25 '17 22:06

Josh


People also ask

What version of TLS does .NET 4.6 use?

You must update and retarget to NET Framework 4.6 or later versions to use TLS 1.1 and 1.2.


1 Answers

I had the same issue (Windows 10 and SSL3 / TLS only... not System Default) with a legacy app targeting 4.7.2. My issue was that during the upgrade process over the years we never added in the targetFramework to the system.web > httpRuntime element (Note: it did exist on system.web > compilation element). Before taking bigger steps, ensure your system.web looks something like the following:

<system.web>     <compilation targetFramework="4.7.2"></compilation>     <httpRuntime targetFramework="4.7.2" /> </system.web> 

In the above example, swap 4.7.2 for whatever version of the framework you are currently using that is >= 4.7.

like image 119
scottheckel Avatar answered Oct 14 '22 21:10

scottheckel