jquery-ujs icon indicating copy to clipboard operation
jquery-ujs copied to clipboard

Updated CSRF tokens not sent when forms inserted by javascript or Turbolinks

Open travisp opened this issue 9 years ago • 4 comments

Example issue:

  1. A page is utilizing fragment caching and is caching a non-remote form (perhaps a Contact Us form that is always in the "new" state)

  2. The user navigates to that page using turbolinks.

  3. The user submits the form on that page and then receives a CSRF token validation error

I think it could be argued that this is not a concern of jquery-ujs, but jquery-ujs does attempt to solve the issue of cached non-remote forms. jquery-ujs currently calls rails.refreshCSRFTokens() on initial page load, where it goes through each form (including non-remote forms) on the page and updates all of the csrf param elements with the current token value from the header. The comment in the source code says:

Make sure that all forms have actual up-to-date tokens (cached forms contain old ones)

This works unless the page is loaded by turbolinks (neither turbolinks nor jquery-ujs will update the cached csrf token), or is otherwise updated by javascript (for example, a js.erb response that inserts a cached form into the current page).

I think there are a couple of ways jquery-ujs could handle this (for example, calling refreshCSRFTokens() on form submit), unless it seems more appropriate as an update to Turbolinks and manual usage of refreshCSRFTokens in applications updating forms with javascript. Given that both turbolinks and using js.erb to update pages are fairly standard ways for rails developers to update the page, I think it could be helpful if jquery-ujs could better handle forms that are cached.

Would a PR be welcome for this in jquery-ujs?

travisp avatar Feb 08 '16 23:02 travisp

+1

This on main application.js solves it in the meanwhile:

$(document).on('page:load', function(){
    $.rails.refreshCSRFTokens();
});

bluehallu avatar Feb 13 '16 19:02 bluehallu

Just been bitten by this using Rails 5.0.2. @bluehallu's suggestion seems to resolve it. This feels like really basic usage of Rails & forms, I'm surprised it's not been resolved.

raldred avatar May 24 '17 16:05 raldred

what the heck is .on('page:load')? I can't find documentation for it anywhere, and it never fires for me.

winterblack avatar Dec 19 '18 19:12 winterblack

According to this SO answer , since Rails 5 it is now turbolinks:load , but it's not firing either for me. Tokens are still invalid .

Edit: The $(document).on('turbolinks:load', function(){ does work, I didn't check a dumb mistake in my application.js file Check you have jquery as well as jquery_ujs (for $.rails) imported before declaring this.

//= require jquery
//= require jquery_ujs

$(document).on('turbolinks:load', function(){
   $.rails.refreshCSRFTokens();
});

Ex-Ark avatar Apr 08 '19 14:04 Ex-Ark