Enabling HSTS (HTTP Strict Transport Security)

Overview

The Strict-Transport-Security header (HSTS) tells browsers to always connect to your site over HTTPS. After a browser sees the header once, it will refuse to make plain HTTP requests to your domain until the header’s max-age expires, even if a user types http:// or clicks an old link.

There are two ways to get HSTS on a site behind the WAF: set it in your application, or ask us to set it at the edge.

The WAF passes the Strict-Transport-Security header from your application through to visitors unchanged. Setting it in your app keeps you in control of the exact max-age and directives, and most frameworks make it a one-line change.

Rails

Set force_ssl in config/environments/production.rb:

config.force_ssl = true

This enables the ActionDispatch::SSL middleware, which redirects HTTP requests to HTTPS and sends an HSTS header with a 2 year max-age and includeSubdomains on. To adjust the values:

config.ssl_options = { hsts: { expires: 1.year, subdomains: false } }

Django

Set the HSTS settings in settings.py (they default to off):

SECURE_HSTS_SECONDS = 31536000  # 1 year
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = False

SecurityMiddleware then adds the header to every HTTPS response.

Express / Node

The helmet middleware sends HSTS by default with a 1 year max-age and includeSubDomains:

const helmet = require("helmet");
app.use(helmet());

To adjust the values:

app.use(
  helmet({
    strictTransportSecurity: {
      maxAge: 31536000,
      includeSubDomains: false,
    },
  })
);

Or: We Set It at the Edge for You

If you would rather not touch your application, open a support ticket and we will enable HSTS at the edge. No problem at all. There are two preset configurations:

  • HSTS sends Strict-Transport-Security: max-age=31536000 (1 year)
  • HSTS Full sends Strict-Transport-Security: max-age=31536000; includeSubdomains; preload

Enabling HSTS at the edge also turns on the three baseline security headers (X-XSS-Protection, X-Frame-Options, X-Content-Type-Options), since they are part of the same setting.

Two things to check before asking for HSTS Full:

  1. includeSubdomains applies the HTTPS-only rule to every subdomain of your apex domain. Make sure all of your subdomains serve HTTPS before enabling it.
  2. preload signals that your domain may be submitted to the browser preload list, which hardcodes the HTTPS-only rule into browsers themselves. Preload list removal is slow, so treat this as a long-term commitment.

A Word of Caution

HSTS is close to irreversible from a visitor’s point of view. Once a browser has seen the header, it will refuse HTTP connections to your domain until max-age runs out. If you are not certain every part of your site works over HTTPS, start with a short max-age (an hour or a day) in your application, confirm nothing breaks, and then raise it.

Need Help?