Web.config Redirect to HTTPS Except for Localhost

by Michael Szul on

Recently, I added LetsEncrypt SSL certificates to all of my web sites in Azure with the help of this well-written blog post by Ray Wang. The push for HTTPS, even for the smallest web sites, has reached epic proportions, and the fact that LetsEncrypt is free, and there is a solid Azure Extension for automatic retrieval and renewal, left me with little excuse not to make the move.

Once you have your web sites set up with HTTPS, you don't really want people visiting the non-SSL version, so for ASP.NET or IIS hosted applications, you want to throw in a redirect. That's pretty easy.

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
          <system.webServer>
              <rewrite>
                  <rules>
                      <rule name="HTTP to HTTPS redirect" stopProcessing="true">
                          <match url="(.*)" />
                          <conditions>
                              <add input="{HTTPS}" pattern="off" ignoreCase="true" />
                          </conditions>
                          <action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
                      </rule>
                  </rules>
              </rewrite>
          </system.webServer>
      </configuration>
      

The above web.config has the appropriate redirect rules to push your users over to the SSL version of your web site. The problem? When developing on your local machine, this will also attempt to push you to an SSL version of localhost.

You can fix this by adding some exceptions using the negate attribute of conditionals.

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
          <system.webServer>
              <rewrite>
                  <rules>
                      <rule name="HTTP to HTTPS redirect" stopProcessing="true">
                          <match url="(.*)" />
                          <conditions>
                              <add input="{HTTPS}" pattern="off" ignoreCase="true" />
                              <add input="{HTTP_HOST}" matchType="Pattern" pattern="^localhost(:\d+)?$" negate="true" />
                              <add input="{HTTP_HOST}" matchType="Pattern" pattern="^127\.0\.0\.1(:\d+)?$" negate="true" />
                          </conditions>
                          <action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
                      </rule>
                  </rules>
              </rewrite>
          </system.webServer>
      </configuration>
      

The two added conditionals will negate the HTTPS redirect for URLs that contain localhost or 127.0.0.1, including ones where a port is specified, which is important since most development servers listen on a port other than the standard port 80.