web.config tips: HTTP to HTTPS redirects and disable access to folder

Tags: .net, asp.net, tips

This is just a quick note with few (I hope) useful web.config tips/settings.

1. HTTP ⇝ HTTPS rewrite without WWW prefix

IIS URL rewrite module is a great way to redirect request from one place to another. I'll admit, I didn't dive VERY deeply into it, but enough to get some sense of HTTP to HTTPS redirect without www prefix, because www prefix is so 1990s right? Right.

After you install this module on your machine, you can add some additional configuration settings under <system.webServer> element:

<system.webServer>
    <rewrite>
        <rules>
            <rule name="HTTP canonical redirect to HTTPS" stopProcessing="true">
                <match url="^(_*)(.*)" />
                <conditions logicalGrouping="MatchAll" trackAllCaptures="true">
                    <add input="{HTTP_HOST}" pattern="^www\.(.*)" />
                    <add input="{HTTP_METHOD}" pattern="GET" />
                    <add input="{SERVER_PORT}" pattern="80" />
                </conditions>
                <action type="Redirect" url="https://{C:1}/{R:2}" redirectType="Permanent" />
            </rule>
            <rule name="Redirect to HTTPS" stopProcessing="true">
                <match url="(.*)" />
                <conditions>  
                    <add input="{HTTPS}" pattern="^OFF$" />
                </conditions>  
                <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
             </rule>
            <rule name="HTTPS canonical redirect" stopProcessing="true">
                <match url="^(_*)(.*)" />
                <conditions logicalGrouping="MatchAll" trackAllCaptures="true">
                    <add input="{HTTP_HOST}" pattern="^www\.(.*)" />
                    <add input="{HTTP_METHOD}" pattern="GET" />
                    <add input="{SERVER_PORT}" pattern="443" />
                </conditions>
                <action type="Redirect" url="https://{C:1}/{R:2}" redirectType="Permanent" />
            </rule> 
        </rules>
    </rewrite>
</system.webServer>

We have 3 redirects in total and the order of them is not important in this case.

The first rule redirects http://www.domain.com to https://domain.com but doesn't touch requests to http://domain.com

The second rule redirects everything from HTTP to HTTPS, but doesn't remove www prefix (which is being done by the first rule).

The third rule removes www prefix for every HTTPS request.

So given those all rules, we now have full support for any variant of redirect from http to https. Mission accomplished.

1,5. Let's Encrypt support

This is one additional tip related to URL rewrite module and Let's Encrypt free certificates at the same time. Despite LE tooling for Windows not being very much polished yet, it's still rather easy to use(*).

LE checks if you're authorized to request for new a SSL cert (or renew existing) for a given domain by searching for a special file in a .well-known subfolder of your website over HTTP. But if you have defined all those redirects above, IIS will redirect any request to HTTPS which LE apparently doesn't get (which makes sense). So you need to either temporarily disable redirects (bad idea if you're just renewing cert) or just add one additional rule (preferably at the top) that will ignore HTTP to HTTPS redirect for this one special folder:

<rule name="Ignore Let's Encrypt HTTPS redirect" stopProcessing="true">
    <match url="\.well-known(.*)" ignoreCase="true"/>
    <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
    </conditions>
    <action type="None" />
</rule>

Also keep in mind, that you can remove this special folder (or just its contents) after you've created/renewed certificate.

2. Disable external access to a folder

In our startup, we want to restrict access to a certain folder and subfolders, so that users can't just type URL to access resources they shouldn't be allowed to access.

Fortunately, web.config in ASP.NET supports settings for specific folder with <location> element. You just need to specify path to this folder, remove all handlers and add HttpForbiddenHandler just to definitely say "Well sir, it is forbidden to access this folder from outside, move along, nothing to see here" (w3wp can still access it):

<location path="Data/EventEditionPhoto">
    <system.webServer>
        <handlers>
            <clear />
            <add path="*" verb="*" name="HttpForbiddenHandler" type="System.Web.HttpForbiddenHandler" />
        </handlers>
    </system.webServer>
</location>

With this simple setting in place, your data should be kept away from all those prying eyes.

(*) At least it's easier than generating CSR and private key on CA website and then converting from OpenSSL format to PFX with password. I know, comparing OV/EV certs to DV certs is like comparing mercedes to seat, but sometimes you don't need mercedes with its lane assists, automatic parking and other AI super-stuff, because sometimes you're happy with just the plain old ABS/ESP.

Read also

The ugly truth behind pretty URLs

Attribute routing is quite handy feature of ASP.NET MVC. But it can also be the reason your web app is so slooow.

T4MVC model unbinders

Sometimes you need to write some infrastructure code just to get basic stuff working. I don't like it either, so here're some tips about T4MVC that might ease your pain.

Data export tools for .NET

How to export data from .NET to PDFs, Word/Exel documents or CSVs.

Comments