Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • JavaScript • Angular
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

Fix automatic re-routing of http:// to https:// on localhost in Web Browsers


:P
On this page:
Edit this Post

If you're a developer and you are running multiple development Web sites locally on localhost you may have run into issues with not being able to access http://localhost or even http://localhost:5200 with the browser instead immediately redirecting to https://localhost or https://localhost:5200. No matter what you try at that point, the site always goes to https:// and then fails because there's no certificate there.

Why is this Happening: HSTS

This issue isn't going to bite everyone, but it will cause problems if any of your localhost sites use HSTS security.

A good example is ASP.NET Core which has applications enable HSTS by default so if you use it, and also use some other local development environment that is not .NET you're likely to hit this problem. Any local development that uses HSTS will affect all other local sites you might work on locally regardless of whether these other apps are using HSTS or not.

HSTS stands for HTTP Strict Transport Security which is a server requested header directive that instructs the client to automatically switch non-secure http:// requests to https://.

It's typically initiated by the server which sends an HTTP header like this:

Strict-Transport-Security: max-age=31536000;

Notice that the header has a max-age which causes the browser to cache this setting for that duration unless explicitly reset via another header request or explicit clearing.

When the client sees this it initiates the HSTS policy for the domain and once set, any request that comes in for http:// is then immediately and automatically changed into a request for https://. For the first request though the server does a redirect to https:// and sends the Transport-Security-Header:

Any subsequent requests from the client then are made over https://:

That all sounds perfectly fine, except for the fact the setting is essentially cached by the client on a per domain level where the domain includes different ports and even sub-domains. The browser 'remembers' the settings and as soon as you go to http:// on a new navigation it immediately jumps to https://.

The following is accessing a site on localhost that is not set up for HSTS or https:// for that matter:

You can see that even though the browser immediately redirects to https:// not even hitting the server - it looks like it's creating a fake redirect on the client as the server is not automatically redirecting. If you go to this same site when no HSTS caching is active from the ASP.NET Core site previously, it loads fine in http://. But now with HSTS applied to the ASP.NET Core site, the root site that doesn't use HSTS doesn't work.

The HSTS security policy applies to the entire domain and can even apply to sub-domains if the includeSubdomains flag is set, as it is in ASP.NET's defaults. This means if you're testing 3 different applications on your machine on localhost - including using different ports - and only one of them uses HSTS, the other two now are also affected by the HSTS policy even though they don't use HSTS themselves.

The end result is that you simply cannot open the site via non-secure http://. The site will automatically redirect, and not allow direct http:// access, and... most likely will not work because there's no certificate.

Fun, huh?

Just Fix it

The good news is that you can fix this HSTS mess fairly easily, the bad news is that if you have multiple applications and at least one of them uses HSTS, you probably will have to apply this fix frequently. Any time you run the application that actually uses HSTS, it's going to impose HSTS on all the other apps running on localhost.

The fix is simple enough if you know where to look which is in the network browser settings. You clear HSTS caching via the net-internals/#hsts settings section in your Chromium browser. You can access them with (depending on your browser):

  • chrome://net-internals/#hsts
  • edge://net-internals/#hsts
  • brave://net-internals/#hsts

(should work for other Chromium browsers too)

then go to:

  • Delete domain security policies
  • Put in localhost (or whatever domain)
  • Press the Delete button

Once you've done this you should now be able to once again access http://localhost without any issues.

Yay!

FireFox? Clear Site Data

You'll have the same issues with HSTS in FireFox but the only way that I found to clear all settings about a specific site.

This clears all data related to the site - History, Cookies, HSTS and more so this is a bloody hammer of a solution. I didn't find any other way to reset the HSTS cache, but this blunt tool works.

Live with it!

So yeah, security sucks as it ever did!

"Live with it" seems to be the operating word I hear a lot lately from the security wonks. 'We know this sucks but that's as good as we could figure out how to do this.'

There are a few approaches you can take to this issue on in addition to the fixes above.

Use Https for all Things

The obvious solution is to use https:// all the things, even on localhost. This is getting a bit easier these days as more and more development tools provide easier ways to either use private certificates, or run servers that automatically install local dev certificates for you on installation (like .NET does these days) or offer built in dev certificate management.

If you're using .NET for development, there's no reason to not use https:// for development since it provides integrated development certificates and the default project templates even have options to set up the local site for https (which enables HSTS ironically which isn't exactly the same as 'enabling https` only).

This is not as common yet for client side development tools like Vue or Angular, but there are platform specific packages for most environments. For example, for Vue you can use Vite mkCert Plugin which adds a local dev certificate when you run the app. I suspect more integrated solutions for this are coming in the future so https:// works right out of the box for local servers on any framework.

Using https:// is by far the best solution, but if you're working on legacy applications that might be using an old server like full IIS or IIS Express without a pre-installed SSL certificate this is easier said than done. Creating of local self-signed certificates is still a pain in the ass especially on Windows and for those scenarios the steps above should be helpful to - at least temporarily - clear out the cached HSTS settings.

It pays off to spend a little time to see if you can get https to work with your local Web Server - it just might save some of these unpredictable behaviors further down the line.

Disable HSTS for Local Dev

If HSTS is the problem, one thing you can do is try to not send the HSTS headers when doing local development. Either set an explicit flag or differentiate between explicit

If you are using a tool that supports HSTS, it might be a good idea to disable it on the local machine so that it doesn't pollute other applications on localhost.

For example, in ASP.NET Core you can do something as simple as this:

if (builder.Environment.IsProduction()) 
{
    // only enable in production not on dev
    app.UseHsts();
}

If the rules for deciding are more complex you can create a dedicated configuration setting for this functionality as I do now in most of my apps which disable HSTS locally:

if (wsApp.Configuration.System.UseHsts) 
{  
   // only enable in production not on dev
    app.UseHsts();
}

thisisunsafe Security ByPass Hack

This is an aside that I found useful while I was tracking down this problem before I figured out that the HSTS tracking was an issue.

There's a hack that allows you to bypass various security issues including using an invalid certificate. This hack is a weird one: If you get a security dialog that you cannot bypass like the one above for localhost and https:// access with a certificate error, you can type thisisunsafe anywhere in the active browser window's Viewport. Yes - anywhere as long as the active browser window has focus. Then just type - invisibly - thisisunsafe into the browser and refresh the page.

The page should now come up and display your content. You'll still see the broken security icon in the address bar, but the page loads and works otherwise. This has the same effect as clicking on that button that says I accept the risks.

Once you've done this, the security setting is cached for some time so repeated restarts of the browser continue to bring up the page without the blocking insecure warning page.

This hack won't help you if you have no https:// binding at all on the server because the server won't be listening on the https port. It will however work if the server is responding on that port but without or with a non-validated certificate.

It's not a good idea to use this 'out' as there's obviously a security issue. Better to fix the problem at the root and hopefully the HSTS fix above might provide the clean if temporary fix. If however you just don't have a workaround this thisisunsafe hack is one way to get on with life.

Summary

Browser security is getting to be more and more in the way of development. While the move to secure browser applications is nice, the technologies that drive this and are tied into the browser itself tend to be cryptic and non-transparent, difficult to troubleshoot and manipulate if you run afoul of the settings. In fact, when I originally ran into the https:// redirection issue I conflated it to be a browser 'feature' (because there are options for forcing http:// to https:// via settings as well). Turns out it wasn't the browser at fault, but HSTS. Of course this isn't obvious at all, until you start digging into requests and in my case get scolded on Twitter for blaming shit on browser vendors 😄.

With HSTS it certainly doesn't help that domain policies aren't specific enough to separate between domain + port or even between sub-domains. This non-granular separation seems like a massive oversight of an obvious problem that might affect behavior especially on localhost.

But alas here we are - at least there's a relatively easy fix for this via browser settings - once you know where to look. Well, now you do... until next time you need it when I'll see you back here - I know I will be back 😄

this post created and published with the Markdown Monster Editor
Posted in ASP.NET  Security  

The Voices of Reason


 

Mladen Mihajlovic
November 01, 2022

# re: Fix automatic re-routing of http:// to https:// on localhost in Web Browsers

I have also had some success in using a secure tunneling software like ngrok while in development to access my local site over https. Here's an example blog post https://adamtheautomator.com/ngrok/


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2022