Our error logs occasionally contain legitimate form submissions that cause ActionController::InvalidAuthenticityToken
errors.
My hypothesis is that the CSRF token stored in the user's session cookie has changed at some point after the form was loaded but before it was submitted. This causes a mismatch between the POSTed token and the token in the cookie, leading to this error.
Given that a Rails session cookie expires only when the browsing session ends (ie when the web browser is closed), what are the ways in which this cookie (and the CSRF token it includes) can be changed without closing the browser?
We are using cookies to store session data, which is Rails' default behaviour.
Here's what we know:
InvalidAuthenticityToken
exception have somehow lost their original CSRF token.I now believe there are two ways that invalid CSRF tokens can be submitted by legitimate users.
Note that these apply specifically to Rails 4.2. As I understand it, the "per-form CSRF tokens" feature in Rails 5 may mitigate them.
As per @crazymykl's answer, the user could open the form, then log out in another tab. This would cause the session cookie stored in the user's browser to change. When they came back to the original tab and submitted the form, the token from the form would not match the token in the session, and the error would pop.
As per this rails bug, Safari behaves oddly with caching under some circumstances. Telling it to reopen with the same windows as last time (via Safari > Preferences > General
), opening the form and quitting Safari results in the form being redisplayed.
Submitting that cached form causes a CSRF error. As the opener of the bug concludes, it appears that Safari caches the page, but drops the session cookie. Hence the mismatch.
The solution to this problem is to set a Cache-Control
header with the directive no-store
. (Difference between no-cache
and no-store
explained here).
Further examples welcome :).
Are you using Ajax form to submit the request? Does your page has multiple forms? If so, check your code whether correct csrf token is submitted along with the request. We had similar issue that page is rendered with one csrf token and we used this token to submit form one and we would have got another csrf token but the second was sending old csrf token that result in error. I am not sure how this is helpful but want to share similar problem faced by me
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With