Need Quality Code? Get Silver Backed

Forcing SSL in MVC and WebAPI

22ndOct

0

by Gary H

Three things cannot be long hidden: the sun, the moon, and the truth.

Buddha

If you have pages or API endoints which deal in sensitive information it's common sense to want to protect them from eavesdroppers. In this post we will look at how we can force our site to use SSL and generate a failure if the caller attempts to use an insecure channel. We'll take a look at some options we have on the server and finish up with a more selective approach using action filters.

Brute Force

The first method we will look at is forcing SSL as a configuration setting on the server. To do this we can use the SSL Settings option on our site in IIS. Setting "Require SSL" will force all clients to connect using SSL. Failure to do so results in the site returning a 403.4 - Forbidden response.

Pros

  • Guarantees all connections will be over SSL

Cons

  • Cannot host both SSL protected and standard pages or endpoints

URL Rewriting

The second method also takes place on the server but requires an extension - the URL Rewriting Module. With this installed we can create a rewrite rule in out web.config that will allow us to redirect http calls to https based on rules.

With this approach we can even different rules to different URL's for our site so if we expect our entire site to be https except for the about page we could use a rule snippet like the following.

<rule name="WhiteList - content folder" stopProcessing="true">
  <match url="^content/"/>
  <conditions logicalGrouping="MatchAll" trackAllCaptures="false"/>
  <action type="None"/>
</rule>
<rule name="Redirect to HTTPS" stopProcessing="true">
  <match url="(.*)billing/(.*)" ignoreCase="true" />
  <conditions>
    <add input="{HTTPS}" pattern="^OFF$" />
  </conditions>
  <action type="Redirect" url="https://{HTTP_HOST}/billing/" redirectType="SeeOther" />
</rule>
<rule name="ForceNonHttps" stopProcessing="true">
  <match url="(.*)billing/(.*)" ignoreCase="true" negate="true" />
  <conditions>
    <add input="{SERVER_PORT}" pattern="^443$" />
  </conditions>
  <action type="Redirect" redirectType="Found" url="http://{HTTP_HOST}{REQUEST_URI}" />
</rule>

Pros

  • Flexible approach allows a mix of SSL and non-SSL
  • Built-in, core, supported component

Cons

  • Requires learning the rule syntax
  • Rule explosion when you need subtly different rules on similar paths

Action Filters

Action filters are a way of executing logic before or after a controller method is called. We can write a custom action filter which will allow us to check if the request has ocurred over SSL and then take an appropriate action. Action filters are applied by decorating your controller or action with the name of your action filter attribute. An example action filter may be:

public class HttpsRequiredAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (!String.Equals(actionContext.Request.RequestUri.Scheme, 
                "https", StringComparison.OrdinalIgnoreCase))
        {
            actionContext.Response = 
                new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden)
                {
                    Content = new StringContent("HTTPS Required")
                };
        }
    }
}

In our example we return a forbidden response if the user is not using SSL however it is a simple matter to change this logic to do anything you require. For example we could change the SSL check to only enforce the SSL requirement if Request.IsLocal is false or update the response to return a 301 Redirect to the SSL protected version of the requested resource.

Pros

  • Flexible approach allows a mix of SSL and non-SSL
  • Custom logic means your filter can take any action you can write code to handle
  • Usage is simple - decorate the action or controller to be protected

Cons

  • Changing SSL rules requires a rebuild and redeploy

Find this post useful? Follow us on Twitter

C# , Security

Comments are Locked for this Post