Closed MrJoy closed 4 years ago
It sounds like TurboLinks might be causing this. Would it be possible to remove it and see if that's correct?
Note that Better Errors' CSRF token is not related to Rails' csrf_meta_tags
or verify_authenticity_token
. It looks like we need to change our error message to be more clear about that.
We're seeing the same issue, and we are not using TurboLinks
I agree, I just double-checked and I've been testing with Turbolinks enabled. Can you help me find a reproducible case? I'm linking to a controller action that fails and returns a Better Errors console.
Can you tell me what URL you're using, in other words how do you reach the Rails server?
It would also help to see the network request that is posting to /__better_errors/:id/variables
, and see any JS errors in the console that are being emitted.
It's a POST to /reminder_rules/:id
, where /reminder_rules
, and the relevant portion from routes.rb
is:
authenticate :user do
resources :reminder_rules, except: %i[show]
end
I'll attach a .har
of the POST, and subsequent call to /__better_errors/:id/variables
(once I figure out how to do so on GH Issues). It looks like the cookie for BE's CSRF token is being set on the POST request, but is not being included in the request to the variables
endpoint.
(File renamed from .har because Github is being prickly.)
I can confirm that disabling Turbolinks does not help. (Removed it from Gemfile
, and package.json
, ran bundle
and yarn install
, removed the code to start it in my JS bundle, removed the options to stylesheet_pack_tag
and javascript_pack_tag
.)
I can also confirm that the issue occurs on Chrome 85.0.4183.102, and with GET
requests (e.g. the /edit
endpoint for the same resource).
I'll see about trying to make a simple repro case later tonight.
This happens for me with 2.8.1 as well: https://take.ms/CCXc8 https://take.ms/BpipT
Seeing the same here. The BetterErrors-CSRF-Token cookie isn't being sent to the variables
endpoint. I haven't worked out why yet. The token is being POSTed correctly in the body of the request, just the cookie not sent.
Doing a +1 here - Rails 4.2 , the 2.8.x releases all throw the CSFR token on the right frame (chrome / safari)
I have the same issue with rails 6.0.3.2, ruby 2.6.6 and better-errors 2.8.1
In my case the cookie Path is getting set to the path where the error happens, which means the cookie doesn't get sent with the /__better_errors... request. Can be fixed by adding path: "/"
at lib/better_errors/middleware.rb:116.
response.set_cookie(CSRF_TOKEN_COOKIE_NAME, value: csrf_token, httponly: true, path: "/", same_site: :strict)
I would make a PR but I don't know if this is 100% the right thing to do. I don't know much about Rack and I took a quick look but it wasn't super obvious.
In my case the cookie Path is getting set to the path where the error happens, which means the cookie doesn't get sent with the /__better_errors... request. Can be fixed by adding
path: "/"
at lib/better_errors/middleware.rb:116
In my case this doesn't fix anything, since the cookie is already there at first and thus I'm not even reaching what's inside the block of unless request.cookies[BetterErrors::Middleware::CSRF_TOKEN_COOKIE_NAME]
.
But afterwards, when checking the same thing in the method internal_call
, the cookie isn't available anymore in line 154‽
Commenting out the CSRF checks
return invalid_csrf_token_json_response unless request.cookies[BetterErrors::Middleware::CSRF_TOKEN_COOKIE_NAME] == body['csrfToken']
and
return invalid_csrf_token_json_response unless request.cookies[BetterErrors::Middleware::CSRF_TOKEN_COOKIE_NAME]
works, though.
I guess, the recently introduced CSRF check is still buggy in some cases.
PS: I'm not sure whether it makes any difference, but I'm using BetterErrors together with binding_of_caller
I have the same problem:
In my case the cookie Path is getting set to the path where the error happens, which means the cookie doesn't get sent with the /__better_errors... request. Can be fixed by adding
path: "/"
at lib/better_errors/middleware.rb:116In my case this doesn't fix anything, since the cookie is already there at first ...
Did you delete the existing cookie? It should then get re-set with the correct path.
Did you delete the existing cookie? It should then get re-set with the correct path.
Yes I did and still had the same behaviour.
But I still didn't get a cookie in the check of internal_call
. Only skipping the CSRF check helped in my case.
Thank you @chuckd that's exactly the issue! I was hoping someone would provide a reproducible case, but you identified the issue on the nose. I've got a fix in the works!
Awesome Robin 👏
2.8.2 should fix this issue. Please let me know here if you still see this issue!
On rubygems, the current version is always at 2.8.1 ;)
I'm running Rails 6.0.3.3. I'm using TurboLinks 5.2.0, StimulusJS 1.1.1, and rails-ujs 6.0.3 via Webpacker 5.2.1, and not directly using Sprockets (except for ActiveAdmin). Browser is Safari 13.1.2 on macOS 10.15.6.
My layout includes output of
csrf_meta_tags
in the<head>
section, and my form includes theauthenticity_token
hidden field.When I attempt to trigger BetterErrors in a controller action (
update
), it comes up enough that I see a stack frame, but I don't see the source view / REPL / request info / locals / instance vars on the right. I only see an error about "Invalid CSRF Token". The/__better_errors
endpoint is available and it works fine, however.The problem does not occur with BetterErrors 2.7.1.
I'm not sure If I've got something subtly wrong, or if there's a bug (possibly related to TurboLinks, or the use of Webpacker).
What information can I provide to help diagnose this issue?