Tag Archives: iis

SSL Termination and Secure Cookies/requireSSL with ASP.NET Forms Authentication

If you’re running a HTTPS-only web application, then you probably have requireSSL set to true in your web.config like so:

<httpCookies requireSSL="true" httpOnlyCookies="true"

With requireSSL set, any cookies ASP.NET sends with the HTTP response – in particular, the forms authentication cookies – will have the “secure” flag set. This ensures that they will only be sent to your website when being accessed over HTTPS.

What happens if you put your web application behind a load balancer with SSL termination? In this case, ASP.NET will see the request coming in as non-HTTPS (Request.IsSecureConnection always returns false) and refuse to set your cookies:

“The application is configured to issue secure cookies. These cookies require the browser to issue the request over SSL (https protocol). However, the current request is not over SSL.”

Fortunately, we have a few tricks up our sleeve:

  1. If the HTTPS server variable is set to ‘on’, ASP.NET will think we are over HTTPS
  2. The HTTP_X_FORWARDED_PROTO header will contain the original protocol running at the load balancer (so we can check that the end connection is in fact HTTPS)

With this knowledge, and the rewrite module available in IIS 7 upwards, we can set up the following:

    <rewrite>
        <rules>
            <rule name="HTTPS_AlwaysOn" patternSyntax="Wildcard">
                <match url="*" />
                <serverVariables>
                    <set name="HTTPS" value="on" />
                </serverVariables>
                <action type="None" />
                <conditions>
                    <add input="{HTTP_X_FORWARDED_PROTO}" pattern="https" />
                </conditions>
            </rule>
        </rules>
    </rewrite>

You’ll also need to add HTTPS to the list of allowedServerVariables in the applicationHost.config (or through the URL Rewrite config)

        <rewrite>
            <allowedServerVariables>
                <add name="HTTPS" />
            </allowedServerVariables>
        </rewrite>

With thanks to Levi Broderick on the ASP.NET team who sent me in the right direction to this solution!