---
title: "Rails 5 adds more control to fine tuning SSL usage"
description:
  "Rails 5 gives finer control over HSTS header and has cleaned up options for
  using SSL"
canonical_url: "https://www.bigbinary.com/blog/rails-5-adds-more-control-to-fine-tuning-ssl-usage"
markdown_url: "https://www.bigbinary.com/blog/rails-5-adds-more-control-to-fine-tuning-ssl-usage.md"
---

# Rails 5 adds more control to fine tuning SSL usage

Rails 5 gives finer control over HSTS header and has cleaned up options for
using SSL

- Author: Srihari K
- Published: August 24, 2016
- Categories: Rails 5, Rails

Adding HTTPS support is one of the first steps towards enhancing the security of
a web application.

Even when a web app is available over `https`, some users may end up visiting
the `http` version of the app, losing the security `https` provides.

It is important to redirect users to the `https` URLs whenever possible.

## Forcing HTTPS in Rails

We can force users to use HTTPS by setting `config.force_ssl = true`.

If we look at Rails source code, we can see that when we set
`config.force_ssl = true`, a middleware `ActionDispatch::SSL`, is inserted into
our app’s middleware stack :

```ruby
if config.force_ssl
middleware.use ::ActionDispatch::SSL,config.ssl_options
end
```

This middleware, `ActionDispatch::SSL` is responsible for doing three things :

1. Redirect all `http` requests to their `https` equivalents.

2. Set `secure` flag on cookies to tell browsers that these cookies must not be
   sent for `http` requests.

3. Add HSTS headers to response.

Let us go through each of these.

### Redirect all http requests to their https equivalents

In Rails 5, we can configure the behavior of redirection using the `redirect`
key in the `config.ssl_options` configuration.

In previous versions of Rails, whenever an `http` request was redirected to
`https` request, it was done with an HTTP `301` redirect.

Browsers cache 301 redirects. When forcing https redirects, if at any point we
want to test the `http` version of the page, it would be hard to browse it,
since the browser would redirect to the `https` version. Although this is the
desired behavior, this is a pain during testing and deploying.

Rails 5 lets us
[specify the status code for redirection](https://github.com/rails/rails/pull/21520),
which can be set to `302` or `307` for testing, and later to `301` when we are
ready for deployment to production.

We can specify the options for redirection in Rails 5 as follows :

```ruby
...
  config.force_ssl = true
  config.ssl_options = {  redirect: { status: 307, port: 81 } }
...
```

If a redirect status is not specified, requests are redirected with a `301`
status code.

There is an [upcoming change](https://github.com/rails/rails/pull/23941) to make
the status code used for redirecting any non-GET, non-HEAD http requests to
`307` by default.

Other options accepted by `ssl_options` under `redirect` key are `host` and
`body` .

### Set secure flags on cookies

By setting the `Secure` flag on a cookie, the application can instruct the
browser not to send the cookie in clear text. Browsers which support this flag
will send such cookies only through `HTTPS` connections.

Setting secure flag on cookies is important to prevent cookie hijacking by
[man in the middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack).

In case of a "man in the middle" attack, the attacker places oneself between the
user and the server. By doing this, attacker aims to collect cookies which are
sent from user to server on every request. However, if we mark the cookies with
sensitive information as `Secure`, those cookies won't be sent on `http`
requests. This ensures that the browser never sends cookies to an attacker who
was impersonating the webserver at an `http` end point.

Upon enabling `config.force_ssl = true`, the `ActionDispatch::SSL` middleware
sets the `Secure` flag on all cookies by default.

### Set HSTS Headers on Responses

[HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) or "HTTP
Strict Transport Security" is a security enhancement by which applications can
specify themselves as HTTPS-only to complying browsers.

HSTS capabilities of a browser can be used by sending appropriate response
headers from the server. When a domain is added to the HSTS list of a browser,
the browser redirects to the `https` version of the URL without the help of the
server.

Chrome maintains an [HSTS Preload List](https://hstspreload.appspot.com/) with a
list of domains which are hardcoded into chrome as HTTPS only. This list is also
used by Firefox and Safari.

Rails 5 has a configuration flag to set the `preload` directive in the HSTS
header and can be used as follows :

```ruby
config.ssl_options = { hsts: { preload: true } }
```

We can also specify a `max-age` for the HSTS header.

Rails 5 by default sets the `max-age` of HSTS header to 180 days, which is
considered as the lower bound by
[SSL Lab’s SSL Test](https://www.ssllabs.com/ssltest) . This period is also
above the 18 week requirement for HSTS `max-age` mandated for inclusion in
browser preload list.

We can specify a custom max-age by :

```ruby
  config.ssl_options = { hsts: { expires: 10.days } }
```

In Rails 5, if we disable HSTS by setting :

```ruby
config.ssl_options = { hsts: false }
```

Rails 5 will set the value of expires header to 0, so that browsers immediately
stop treating the domain as HTTPS-only.

With custom redirect status and greater control over the HSTS header, Rails 5
lets us roll out `HTTPS` in a controlled manner, and makes rolling back of these
changes easier.

## Links

- [Human page](https://www.bigbinary.com/blog/rails-5-adds-more-control-to-fine-tuning-ssl-usage)
