Rails comes with a built-in support for SSL in form of config.force_ssl
. But what does it exactly do?
SSL middleware
The force_ssl
directive adds the ActionDispatch::SSL
middleware layer which is a Rack middleware for HTTPS requests:
# rails/railties/lib/rails/application/default_middleware_stack.rb...defbuild_stackActionDispatch::MiddlewareStack.new.tapdo|middleware|ifconfig.force_sslmiddleware.use::ActionDispatch::SSL,config.ssl_optionsend...
This middleware does two main things:
SSL/TLS redirect: Redirecting
http
requests tohttps
with the same URL host and path. Both from the Rails server and the browser by requesting HSTS.Secure cookies: Setting the secure flag on cookies so browsers don’t send out any cookies for plain
http
requests.
Configuration
The config.force_ssl
directive can be set per environment in config/environments/[ENVIRONMENT].rb
.
We can adjust the SSL settings with two options, ssl_options
and assume_ssl
.
The ssl_options
directive configures the ActionDispatch::AssumeSSL
middleware. We can use it to redirect to a particular host:
config.ssl_options={redirect: {host: "secure.widgets.com",port: 8080}
Or exclude healthcheck path from the HTTPS redirect:
config.ssl_options={redirect: {exclude: ->request{request.path=~/healthcheck/}}}
The config.assume_ssl
adds additional ActionDispatch::AssumeSSL
middleware that will set the following HTTPS headers:
HTTPS
toon
HTTP_X_FORWARDED_PORT
to443
HTTP_X_FORWARDED_PROTO
tohttps
rack.url_scheme
tohttps
This is useful when running Rails with force_ssl
but behind a load balancer or proxy that terminates SSL connection. This prevents ActionDispatch::SSL
auto-redirect to HTTPS.