Enhance Your .NET HttpClient with HSTS Support

 
 
  • Gérald Barré

HTTP Strict Transport Security (HSTS) is a security feature that instructs clients to connect to a website over HTTPS only. Websites set the Strict-Transport-Security response header to enforce this policy. ASP.NET Core makes it straightforward to send this header, but .NET's HttpClient has no built-in HSTS support. This post shows how to build an HttpClient that honors HSTS, including the HSTS preload list.

The approach uses a custom HttpMessageHandler that reads the Strict-Transport-Security header from responses and automatically upgrades subsequent requests to HTTPS. It also consults the HSTS preload list to upgrade requests for known domains without waiting for a response header.

Add the package Meziantou.Framework.Http.Hsts to your project:

Shell
dotnet add package Meziantou.Framework.Http.Hsts
C#
// Use the HstsClientHandler when creating the HttpClient
using var client = new HttpClient(new HstsClientHandler(new SocketsHttpHandler()), disposeHandler: true);

// Automatically upgrade to HTTPS as api.google.com is in the HSTS preload list
using var response = await client.GetAsync("http://mail.google.com");
_ = response.RequestMessage.RequestUri; // should be https://mail.google.com

// response contains the Strict-Transport-Security header, so the next request is upgraded to HTTPS
await client.GetStringAsync("https://www.meziantou.net/");
await client.GetStringAsync("http://www.meziantou.net/"); // will be upgraded to https

You can also add your own domains to the HSTS policies:

C#
var policies = new HstsDomainPolicyCollection(includePreloadDomains: true);
policies.Add(
    host: "example.com",
    expiresAt: DateTimeOffset.UtcNow.AddYears(1),
    includeSubdomains: true);

using var client = new HttpClient(new HstsClientHandler(new SocketsHttpHandler(), policies), disposeHandler: true);

#Additional resources

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?