add csrf token validation in via request header, add metatag helper #4

Merged
merged 4 commits into from Feb 18, 2012

Conversation

4 participants
Contributor

jeffreyiacono commented Feb 15, 2012

Adds csrf token validation via request headers.

Useful for situations when using ajax: instead of having to pass the csrf token via params, we can now set a metatag with the csrf token's value in the layout's head and use something along the lines of:

(function(jQuery) {
  // set the x-csrf-token for each ajax operation
  // rack / rack_csrf handle the rest
  jQuery.ajaxSetup({
    beforeSend: function(xhr) {
      var token = jQuery('meta[name="_csrf"]').attr('content');
      xhr.setRequestHeader('X-CSRF-TOKEN', token);
    }
  });
}(jQuery));

now the csrf token is always sent on ajax requests via the specified header. Also adds a metatag helper to quickly generate the metatag with the token in place for the developer.

Additionally adds a Gemfile for gem packaging and updates the readme.

Owner

jeffreyiacono commented on 76baa1e Feb 14, 2012

you can now use the jquery ajaxsetup setup a la rails again (in your sinatra app, for example):

(function(jQuery) {
  // set the x-csrf-token for each ajax operation
  // rack / rack_csrf handle the rest
  $.ajaxSetup({
    beforeSend: function(xhr) {
      var token = jQuery('meta[name="csrf-token"]').attr('content');
      xhr.setRequestHeader('X-CSRF-Token', token);
    }
  });
}(jQuery));

just make sure you include the csrf token in a meta tag in your layout's head

@baldowl baldowl added a commit that referenced this pull request Feb 18, 2012

@baldowl baldowl Merge pull request #4 from jeffreyiacono/master
add csrf token validation in via request header, add metatag helper
e73d62d

@baldowl baldowl merged commit e73d62d into baldowl:master Feb 18, 2012

Owner

baldowl commented Feb 18, 2012

Thanks for you contribution.

matehat commented Feb 28, 2012

Hey! That contrib is really great! Any idea when this is going to make it into a rubygem release?

Contributor

jeffreyiacono commented Feb 28, 2012

@baldowl @matehat thanks!

@matehat If you wanted to use it now while waiting for the rubygem release, you can add the following to your Gemfile:

gem 'rack_csrf', git: 'git@github.com:baldowl/rack_csrf.git', ref: 'cec9e5da84494be06a076947a095d1cbda3147d1'

Owner

baldowl commented Feb 28, 2012

I usually let the code rest for a while before packaging (even well test code like this one), just to be sure that nothing is wrong, while using it with Bundler; but you're right @matehat, it's time to ship it!

I'll release the gem later today or tomorrow.

matehat commented Feb 28, 2012

@jeffreyiacono Thanks for the tip!
@baldowl Glad to hear that!

Awesome work from both of you by the way!

sonoman commented May 22, 2013

Hi There. I have a question: how do you do when the only interaction you have with a client application is through a Rest API, but you want to keep a session, and you want to use csrf token ? I mean, you say here that i must send the token in a meta tag in head....but I don't have actually a web page....i only have json documents flying both directions....

Owner

baldowl commented May 22, 2013

It's an interesting question.

First of all, given that tokens are always generated by the server, I'd say that whatever library you decide to use, your API client will have to send an initial, "harmless" request that will have to be exempted from the normal check mechanism and to which the server will reply with whatever you need plus the CSRF token.

Afterward, your API client will have to add the token in a custom HTTP header (see the Readme); the code example just shows that, with a bit of JavaScript, the token can be "extracted" from a meta field populated in your layout, for example, and inserted into the right header without changing anything else.

But you must find a way to share the session with the API client and this could be difficult or impractical... or maybe you could go fully RESTful, forgo sessions, cookies, tokens, etc. and authenticate each and every request because you wrote that there's no page to hack to forge any request, isn't there?

sonoman commented May 23, 2013

yeap, that's the case.....besides, since I'm authenticating with oauth2, I could simply have the client send the bearer token on a header on every request, and probably cache that token in couchabse or similar......thanks !!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment