Putting form_authenticity_token (csrf token) in a cookie instead of in meta tags?

When you generate a default Rails app, it puts this in
application.html.erb:

<%= csrf_meta_tags %>

It does this so the remote forms can be submitted–i.e., so JavaScript
can
submit a form. When jquery-rails is about to submit a form, it looks for
the tags named “csrf-param” and “csrf-token” and from them it
constructs a hidden “authenticity_token” param from it. It gets inserted
in
with the POST data so Rails will accept the request.

I would like to be able to serve identical HTML content for all users,
so
the page can be cached on Varnish or a CDN or whatever. Since the
form_authenticity_token is different for every session, leaving
csrf_meta_tags in the header makes it impossible for a proxy to cache
the
page.

I have an idea for how to fix it but thought I would ask here, to see if
people think there would be problems with it: I could create an
after_action in ApplicationController that looks like this:

after_action :set_authenticity_cookie

def set_authenticity_cookie
cookies[:form_authenticity_token] = form_authenticity_token
ifform_authenticity_token
end

So basically send the form_authenticity_token to the browser in a cookie
instead of putting it in the HTML.

Client-side, I could write a little JavaScript that pulls it out of the
cookie and dynamically creates the meta tags that jquery-rails is
expecting.

  • Questions: *

    1. Does this expose me to any security problems?
    2. Is there any reason this wouldn’t work?

Thanks,

Brian

On Saturday, May 3, 2014 4:39:14 PM UTC-4, Brian Morearty wrote:

constructs a hidden “authenticity_token” param from it. It gets inserted in
after_action in ApplicationController that looks like this:
Client-side, I could write a little JavaScript that pulls it out of the
Brian

I’ll answer the second question first. I’m not sure the
form_authenticity_token will persist. It might. If not, you can use
(and
probably should use) session[:_csrf_token]. Otherwise, I haven’t tested
it, but it seems like it should work.

The first question is probably the bigger concern. The purpose of cross
site request forgery is to insure that requests originate from the
application. It seems your javascript would circumvent that by
inserting
the token in the form. What event will trigger your javascript? Will
any
form that gets submitted, regardless of its origin? If so, IMO, you
have a
significant security risk. In other words, how will you insure that
only
forms obtained from your Varnish server or the application get submitted
and everything else will be rejected?