I've got a really weird issue with Rails 5 (beta1) and it's preventing me from safely submitting any forms.
When running in production mode behind an Nginx (1.4.6 on Ubuntu 12.04) reverse proxy which decrypts SSL, Rails is rejecting my CSRF tokens saying they are invalid despite the fact that the correct token is being submit by the form.
Everything works fine when I turn SSL off in Nginx.
Any help would be appreciated.
Fix by adding more headers in Nginx (X-Forwarded-Ssl on, X-Forwarded-Port 443 and X-Forwarded-Host "your hostname", X-Forwarded-Proto https). The problem was actually in the new way CSRF tokens are checked by ActionController (compares the request.base_url with the origin header)
Related
I have a rails application running on a private subnet, using port 8080, without SSL enabled.
I also have an Apache SSL server on a DMZ, which I use as a reverse proxy to the rails application I mention first.
The problem is, rails include some absolute url in the generated code, with adresses beginning with http://...
If i use config.force_ssl = true as I read here or there, there is a infinite redirection, because rails sees the requests coming as plain HTTP and issues a redirect to HTTPS, but as the client already is.
The solution was simple enough: put this line in the reverse proxy configuration file :
RequestHeader set X-Forwarded-Proto "https"
I would like all HTTP traffic to be redirected to HTTPS on my Rails web app deployed on AWS Elastic Beanstalk.
There is a config option for Rails that forces SSL on all connection. The issue is that without modifying the default nginx config on my EB environment, I am getting a redirect loop. Why am I getting infinite redirect loop with force_ssl in my Rails app?
I'm new to EB and I was wondering how I would go about adding in the proxy_set_header X-Forwarded-Proto $scheme; to nginx.conf using .ebextensions configuration files. Do I copy and paste the current nginx.conf file by SSHing into my EC2 instance and add the header? When I navigate to /etc/nginx/nginx.conf, the HTTPS portion of the config file seems to be commented out, even though I enabled it in the AWS web console.
I have been facing this issue for some time. The best solution for forcing SSL on Rails + Elastic Beanstalk is from Amazon. They have a config file (ebextension) for exactly this purpose. You can find it here:
https://github.com/awsdocs/elastic-beanstalk-samples/blob/830ff9163ef37d0ece8ecf583c1c84223e9266e7/configuration-files/aws-provided/security-configuration/https-redirect/ruby-puma/https-redirect-ruby-puma.config
If you need more information on ebextensions, you can find them in the docs http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/ebextensions.html
Recently I wanted to secure my rails 4.2.1 app with https the easiest way. I found this question as well as this answer about WEBrick+SSL, both referencing to this post which is unfortunately not reachable any more. Then I found this answer recommending to use thin instead (naming other advantages of using thin). Then I followed this step-by-step guide, finally running thin start --ssl --ssl-key-file .ssl/key.pem --ssl-cert-file .ssl/cert.pem -e production with self-signed certificate. My config/environments/production.rb contains config.force_ssl = true.
Now I would like to access the web normally by typing example.com expecting to be automatically redirected to https://example.com but this does not happen. Typing looong https://example.com works fine. Here is a 2-year-old question with similar issue but any answer doesn't work either and something could have also changed since then.
How can I make it work? Or is there any different recent but simple enough way to start using ssl with rails? Thanks!
In your config/environment/production.rb file make sure you have the following:
config.force_ssl = true
Also make sure to update your cookie settings in config/initializers/session_store.rb:
Rails.application.config.session_store :cookie_store, key: '_secure_domain_session', httponly: true, secure: true
You also need to specify secure: true in the config/initializers/devise.rb file if you are using Devise
Also make sure to clear the cache on your browser
If you have a load balancer in front of your website that is terminating the TLS/SSL and then connecting via HTTPS to the backend, this would mean the connection from the load balancer to your server is HTTPS, even though the client connection to the load balancer is not. Your load balancer should send the X-Forwarded-Proto header which Rails should take into account.
If you are running Rails under Passenger inside Nginx (or Apache), you may need to configure that to forward the header and/or port.
passenger_set_header X-Forwarded-Proto $http_x_forwarded_proto;
passenger_set_header X-Forwarded-Port $server_port;
Note, however, that Rails looks first at the HTTPS environment variable before it looks at the header, and that might be set to "on" because connection to your web server is HTTPS.
In that case you can redirect all traffic from HTTP to HTTPS inside Nginx:
if ($http_x_forwarded_proto != 'https') {
rewrite ^ https://$host$uri permanent;
}
On a rails 2.3 application i have this simple code
redirect_to resource_url(resource)
I make the request using a SSL connection (https) but it redirects to the non SSL version (http)
I checked and resource_url is throwing http without ssl.
How Rails knows if the protocol is https? My setup uses Nginx and 3 mongrels with load balancers.
I wonder if the issue is that my mongrel instances uses http.
Is there a way to let mongrel instances know that the connection to nginx was with ssl?
Is this really my issue?
This was caused because nginx was configured with a load balancer. Basically the browser makes a SSL connection to Nginx, but nginx make a internal connection through http to the mongrel instances, and they don't know if the original connection was over SSL.
The solution is add this to the nginx config
proxy_set_header X-Forwarded-Proto $scheme;
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.
Alternatives (What Doesn't Work)
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:
$http_header
proxy_set_header
more_set_headers
$cookie_COOKIE
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.
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.
You should look at the rack-ssl-enforcer gem. Removes the problem from rails and it's highly configurable to your needs.
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