Reputation: 3954
I'm working with a Rails app that sits behind a reverse-proxy server (Nginx), and I need the session cookie for the Rails app to be flagged Secure
. However, when I set it like below,
Application.config.session_store :cookie_store, :key => '_app_session', :secure => true
Rails stops sending the _app_session
cookie.
I know Rails is holding it back because I am hitting Rails directly with curl -v
, and I can see the _app_session
cookie when I omit :secure => true
.
How do I force Rails to send the secure cookie over the HTTP connection?
Note: It's okay, in this specific scenario, to be sending a secure cookie over HTTP. This traffic is happening in an area considered secure before getting wrapped in SSL and sent out into the world. Further, "terminating SSL upstream is quite common", so I'm not the first to have a setup like this.
Here's what I've tried already:
I wrote a script in Lua that adds Secure
to the cookie. It worked, but my boss said we can't have Lua in the Nginx.
I couldn't figure out how to use the following directives in Nginx to achieve what I wanted:
I tried adding set_proxy_header
and add_header
as suggested here, but it didn't work, and I suspect there's something peculiar about our setup that may be causing that.
Finally, hypothetically I could write a C module for Nginx, but I'm not going to do that.
Upvotes: 1
Views: 4466
Reputation: 189
If your application is always secure, the best way is to add proxy_cookie_flags
(since Nginx version 1.19.3) configuration to your Nginx (in your desired location
). There is no need for an additional script.
For all cookies use:
proxy_cookie_flags ~ secure;
Check more in the documentation: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cookie_flags
Upvotes: 0
Reputation: 933
You should look at the rack-ssl-enforcer gem. Removes the problem from rails and it's highly configurable to your needs.
Upvotes: 0
Reputation: 3954
I added the following to the relevant location
blocks in my Nginx conf file:
proxy_set_header X-Forwarded-Proto https;
It didn't work before because I had used X-Forwarded-Proto $scheme
at the suggestion of the link in my question. I don't know why that didn't work, but doing
$ curl -v -H "X-Forwarded-Proto: https" http://localhost:95/app-path
does return the expected _app_session
cookie, with the Secure
flag set, so clearly RoR just needs to know that the secure cookie will end up going out over https.
Update (Jun 2015)
The reason why I had trouble with this was because our servers were proxy passing http
requests to themselves for https
and not setting X-Forwarded-Proto
first. Once I understood our topology better, I was able to do X-Forwarded-Proto $scheme
before the first proxy pass. That is the correct solution.
Upvotes: 6