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!