How can I see the TLS version of an incoming API request - ASP.NET

510 Views Asked by At

I have a web app hosted on Microsoft Azure that includes a Web API. I am targeting .NET Framework 4.5.

I am working through all the required steps in order to make TLS 1.2 the minimum version required for incoming requests.

Before I officially switch to TLS 1.2 minimum for incoming requests, I would like to know if anyone is currently using older TLS versions, since we have third parties using our API.

Is there a way to detect the TLS version that was negotiated in a specific API request?

For example, I have this API call below. What code can I write using .NET Framework 4.5 that will get the TLS version that was negotiated?

        [HttpGet]
        [Authorize(Roles = "User")]
        public HttpResponseMessage GetFirstName()
        {
            // I would like to add code here to get TLS version negotiated so I can log it

            var email = User.Identity.GetUserName();
            ApplicationUser userFound = GetUserByEmail(email);
            if (userFound == null)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Error: No such user.");
            }
            var firstName = new { FirstName = userFound.FirstName };

            return Request.CreateResponse(HttpStatusCode.OK, firstName);
        }

I know I eventually need to upgrade .NET Framework altogether, but I need a quick solution on 4.5 before I can tackle that.

1

There are 1 best solutions below

3
Suresh Chikkam On

Absolutely, Panagiotis Kanavos point is valid. Upgrading to a supported version of .NET Framework, such as 4.6.2 or later may help more.

As you can check here in MS doc saying that if you are using 4.5v you need to upgrade for the latest version. enter image description here

I have tried for the newer version of .NET Framework 4.6.1. I can access the TLS version information directly from the SslStream class.

using System;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web.Http;

namespace YourNamespace.Controllers
{
    public class YourController : ApiController
    {
        [HttpGet]
        public async Task<HttpResponseMessage> Get()
        {
            await LogNegotiatedTLSVersion(Request);

            // Your existing code here

            return new HttpResponseMessage()
            {
                Content = new ObjectContent<string>("Hello, World!", new JsonMediaTypeFormatter()),
            };
        }

        private async Task LogNegotiatedTLSVersion(HttpRequestMessage request)
        {
            object property;
            if (request.Properties.TryGetValue("MS_HttpContext", out property))
            {
                var context = (System.Web.HttpContextWrapper)property;
                var stream = context.Response.Filter as System.Web.HttpBufferedOutputStream;

                if (stream != null)
                {
                    var sslStreamField = stream.GetType().GetField("_sslStream", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
                    var sslStream = sslStreamField?.GetValue(stream) as System.Net.Security.SslStream;

                    if (sslStream != null)
                    {
                        // Log the negotiated TLS version
                        Console.WriteLine($"Negotiated TLS version: {sslStream.SslProtocol}");
                    }
                }
            }
        }
    }
}
  • The SslStream.SslProtocol property is used to get the negotiated TLS version. The AuthenticateAsServer method is called to authenticate the server side of the connection.