I've got a issue where some users that go idle on my site for a period of time receive a CSRF error when submitting post requests. I don't want to disable the security feature in Rails because of its importance, so I was thinking to display a page timeout alert instead. However I cannot find anywhere what the Rails default timeout is for the authenticity_token. Can someone please point me in the right direction?
Thanks in advance.
UPDATE
When I look at cookies for my site Chrome shows that the session cookie expires when the browsing session ends. If that's the case and the reason that I get the CSRF error is due to an expired session, how does it expire if the browser is never closed?
The default behavior is for the CSRF protection to use cookie-based sessions, and for the cookies to expire when the session expires. It sounds like the session is expiring, causing the CSRF error.
Related
This is a Rails 5.1 web app migrated from a Rails 4 app (in turn migrated from a Rails 3 app) deployed to Datica (which is Docker based).
After each deployment, our logs record spikes in the occurrence of "Can't verify CSRF token authenticity" warnings and corresponding 401 statuses. The front-end is a React app, with most client-server communication happening over XHR, so some people receive 401 multiple times. Refreshing the browser has solved the 401 status for me twice, so I think the fall-off in the spikes indicates people refreshing or ceasing to use the app because it isn't working for them (see screenshot of the log graph showing the spikes).
The app uses cookies for session storage. The CSRF token is in the body of the page when it was first loaded. What I have observed would be explained by the cookies being given a new CSRF token, so that there is a mismatch between the CSRF token in the body of the page and that in the session, but I do not understand what would cause the server to issue a new CSRF token after a deployment.
Thinking this might be due to a delay in the newly launched instances receiving the Origin header, or the old instances ceasing to receive it, I set config.action_controller.forgery_protection_origin_check = false in application.rb. However, there were spikes after deploying last night and again this morning (and it wouldn't really make sense anyway since refreshing the browser appears to solve the problem).
Any ideas as to how a deployment would cause the server to issue new CSRF tokens to sessions? Or any other ideas or other hypotheses?
Thank you!
The problem was that MyApp::Application.config.secret_key_base was never set. Back when the app was migrated from Rails 3 to 4, the recommendation was to wait until the user base was completely on 4 before uncommenting that line. But that never happened.
I presume that if that secret_key_base isn't set, it automatically generates an in-memory key base for generating CSRF tokens, resulting in a new key base every deployment.
I'm developing an app that logs into a HTTPS website. After authentication, the website sends a final cookie that is marked as 'Secure'.
The app works when I use defaultSessionConfiguration() for NSURLSession().
When I change one line in the app to use the backgroundSessionConfigurationWithIdentifier() then I can't proceed past the authentication stage. I do get a webpage showing that I am authenticated but subsequent requests return the login page.
It appears that the "authentication successful cookie" is not present in the shared cookie storage.
This cookie is the only cookie that the website marks as "Secure". Note that this HTTPS website does all it transactions via HTTPS.
TL;DR
What does the NSURLSession background session do differently from the default session to lose a Secure cookie??
EDIT: I've done some more work.
When NSURLSession redirects using the backgroundSessionConfiguration it appears to ignore cookies that were sent in the Header of the redirect? (I think the cookie being "Secure" may not be critical.)
The redirect works correctly when the defaultSessionConfiguration is specified.
It turns out that this is a known bug. Apple r. 16,852,027.
The backgroundSession is known to ignore new cookies on redirect. The solution is to use a defaultSession to get the cookies and then continue using backgroundSession.
See Apple Developer Forum post
I have a problem regarding the Session Timeout handling in Spring Security in our spring application. Actually the application is configure for 1 hour session timeout in SiteMinder. So after 1 hour, the application session is timed out. After session time out if we do any operation on the page, instead of redirecting the user to invalidsession.jsp, as its configured in our security-context.xml file. Currently when we click on the submit button a search button, an ajax call is made and its giving a wrong message saying records are not found, which is confusing for the user. How to handle this issue in such a way that after session time out, instead of ajax call, the application should redirect to invalidsession.jsp
A few users are getting a 422 ActionController::InvalidAuthenticityToken error when POSTing a form.
It happens to a minority of users some of the time. If they try their request again later, it often works.
The authenticity token is getting sent along in every case. I'm assuming the client isn't sending the session cookie along with the POST (that would explain why the server can't verify the token). Why would this be?
Finally, the form is submitted via javascript ($('#new_user')[0].submit()), would that somehow prevent the session cookie from being sent?
Disabling the verify_authenticity_token before_filter is unfortunately not an option.
We have run into this scenario with one of our apps. We store our sessions in memcached and if the session is evicted from the cache or the session expires any subsequent post/put/delete raised a 422. We got round this by implementing a before filter 'requires_login?' that checked the session and logout the user out if the session had expired. We then moved the method protect_from_forgery in the application controller to run after requires_login?
E.G
before_filter :requires_login?
protect_from_forgery
Hope this makes sense
In rails it will generate a session_id if properly set up session configuraions, then after rendering the web page the seesion_id will store on client with cookie; however if the cookie value is changed by client before sending request to web server, how rails to check the change? Now i can not find any clues for rails to check the change, if it doesn't to check and the changed seesion_id is existed in web server session store, other session's data will be dispalyed for the current browser user.
If someone is clear on the question can you explain it for me? thank you in advance.
The cookie is cryptographically signed. See:
https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/cookies.rb
Note that signing the cookie doesn't mean the same thing as encrypting it. The user can see the contents of their session with a bit of fiddling but can't alter it without breaking the signature.
If you want to hide the contents of your sessions from your user, don't use the cookie store.