rails: Request origin does not match request base_url
I am running the Rails 5.0.0 beta1 and after deploying to production have noticed something odd. My application is running being an Nginx reverse proxy which decrypts SSL.
Every time I try to submit a form, a ActionController::InvalidAuthenticityToken is raised. I have managed to narrow this down to line 399 in ActionController. The problem is that the request origin has https://
as the protocol and the request base_url has http://
as the protocol.
I have tried setting the X-Forwarded-Proto
header and using config.force_ssl = true
but neither made any difference.
I have not yet figured out a way to isolate a failing test case but am happy to look into it if anyone has any suggestions.
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 45
- Comments: 33 (3 by maintainers)
Commits related to this issue
- Fix Rails 5 CSRF error Add http header on nginx reverse proxy setting. See also https://github.com/rails/rails/issues/22965 — committed to long-live-net/france by ngzm 6 years ago
- Fix Rails 5 CSRF error Add http header on nginx reverse proxy setting. See also https://github.com/rails/rails/issues/22965 — committed to ngzm/g-link by ngzm 6 years ago
- Set correct headers for incoming SSL request Rails application in production was complaining that ``` Request origin does not match request base_url ``` This is due to nginx headers being set incor... — committed to abhchand/girder-ansible by abhchand 4 years ago
- [Girder] Set correct headers for incoming SSL request Rails application in production was complaining that ``` Request origin does not match request base_url ``` This is due to nginx headers being ... — committed to abhchand/reely-ansible by abhchand 4 years ago
- Force SSL + Forward SSL from Nginx to the container Was causing http urls instead of https. see: https://github.com/fablabbcn/smartcitizen-api/issues/166 Solution is to force use SSL, and forward it... — committed to fablabbcn/smartcitizen-api by viktorsmari 4 years ago
- bug fix nginx.conf attempt based on https://github.com/rails/rails/issues/22965 — committed to canriquez/portfolio by canriquez 4 years ago
- Updating nginx config to ensure authenticity token is accepted See https://github.com/rails/rails/issues/22965 — committed to domhnall/renupharm by domhnallmurphy-examtime 6 years ago
- k8s: fix CSRF token authenticity error in Rails. Fix issue described in [1]. We were incorrectly overriding the X-Forwarded-Proto header from the ingress, which caused CSRF token validation in Rails ... — committed to danbooru/danbooru-infrastructure by evazion 3 years ago
- Fixed issue 'Request origin does not match request base_url' from https://github.com/rails/rails/issues/22965 — committed to fguillen/RailsSkeleton by fguillen 3 years ago
- Set correct headers for incoming SSL request See rails/rails#22965 — committed to deltacy/istos.cy by despo 2 years ago
- Set correct headers for incoming SSL request See rails/rails#22965 — committed to deltacy/istos.cy by despo 2 years ago
I also ran into this issue. I’ll describe it differently to help with future searches.
Submission of any form to Nginx proxying to a Puma unix socket running a Rails 5.0.0.beta1 app responds with:
and throws:
even though the App’s CSRF is set up correctly. The app works in development (puma or thin, without Nginx), and worked in Nginx/Puma/Rails-4.2. I don’t know if this is specific to using Puma, but seems like the same problem could exist with other servers (unicorn, passenger, etc.)
I don’t know if this behavior change is an error or intended.
I can confirm @tpbowden’s solution worked for me as well. In my nginx configuration, I setup the app to proxy to puma listening on a unix socket. Here are the relevant parts of the configuration.
My problem was similar, using heroku and cloudflare, solution was:
from: http://til.obiefernandez.com/posts/875a2a69af-cloudflare-flexible-ssl-mode-breaks-rails-5-csrf
I’ve just done a bit more research and it is definitely the intended behaviour. It can be disabled in your app config using
config.action_controller.forgery_protection_origin_check = false
. It is enabled by default however.Thanks so much : I was missing this line :
proxy_set_header X-Forwarded-Proto $scheme;
It might not be related but just for your information.
I recently encountered the same issue. For those who do not use Nginx reverse proxy, you can create a middleware to rewrite
X-Forwarded-Proto
based on CloudflareCF-VISITOR
header, here is my solution:In
config/application.rb
:You can also rewrite
X-Forwarded-Port
andX-Forwarded-Ssl
andX-Forwarded-Host
by the same technique. In my case, rewrote onlyX-Forwarded-Proto
solved my problem.A reference for
CF-Visitor
header:https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-
The issue isn’t related to Puma and would happen to any web server running behind a reverse proxy which isn’t passing the correct headers through. The way I managed to figure out how this issue was being caused was by following the error down the stack trace.
The root of the issue is the code in
request.origin == request.base_url
, which compares theOrigin
header’s value against the base_url which is build up by aRack::Response
. There are 3 parts to this value, thescheme
, thehost
and theport
. All three of these are calculated based on a series of headers which not present by default when using a reverse proxy.You can follow the source for
Rack::Request#base_url
here and it will become clear by looking in your web logs which headers are missing.Fix by adding more headers in Nginx (X-Forwarded-Ssl on, X-Forwarded-Port 443 and X-Forwarded-Host hostname)
For those using Apache, this worked for me:
@afair You, Sir, have saved a lot of my time. Thank you.
If you look at @afair’s comment above he was referenced a correct Nginx config, you just need to add the x-forwarded headers related to ssl. I figured out which ones were missing by digging though the source code of Rack’s request object to find out how it determine’s the protocol of the request.
@Onumis Thank so much! I turn Cloudflare SSL to Full mode and fixed the problem.
This config helped me:
Thanks @tpbowden and @afair I was desperatly trying to make any sense of this oddly failing CSRF protection… then I found this issue 👍
ahh, so how did you find out what was missing…and how did you add the missing headers? Thanks so much for the quick reply!