In working through AngularJS and Rails integration, one of the matters that comes up frequently is CSRF protection. This is an important security measure, and this post points to the solution that I found on stackoverflow, and provides the code snippet that I implemented, and how I verified that it seems to be working. This content has also been included in the Rails 3 and AngularJS tutorial, available from the tutorials menu above, and the Rails 4 and AngularJS tutorial, also available from the tutorial menu above, or this specific post within that tutorial.
There is also a more thorough treatment of this content in another post, here (described in more detail at the bottom of this post).
CSRF protection is aimed at avoiding hacking by cross site scripting. In turn, cross site scripting is where javascript on one site causes your browser to perform actions on another site (perhaps one that you have credentials on, and are already logged on to). This is a reasonably esoteric attack that is only likely to be used on high volume web sites (such as facebook and the like), as it relies on someone having built a web site that specifically scripts to target your website. Unless your website is very high volume, what’s the odds that someone will visit this attack web site and also be logged on to the target website (your website). Since it’s good practice to implement CSRF protection, since it’s not very hard, and since we plan one day to have a website that dominates the world that everyone wants to use…..we’re implementing this protection. A good CSRF example (albeit that focuses on Drupal) can be found at epiqo: all your pants are in danger, the wikipedia page also provides good information.
To implement this we’re following the suggestion from stackoverflow: rails csrf protection. This approach is elegant because all the logic appears to be in the application_controller.rb on the server side, there’s nothing for the angular code to do, and no changes made to each individual controller. It also looks like it obeys the security requirements to actually prevent cross site scripting, and many people on stack overflow liked it. I just have a little niggle about whether the cross site scripting might still work – it seems to me that when you send your request with a url in it, that the request will end up with this cookie on it? However, I think the trick here is that Angular is taking something out of the cookie and putting it into the headers, and only javascript that’s on the site itself can do that – someone external can have your browser automatically send the cookie down, but they can’t take information out of the cookie and move it into the headers. It’s very elegant.
An alternative approach is through a project that introduces CSRF into rails and angular, ng-rails-csrf. My feel was that it integrated rails and angular too closely, I wasn’t keen to have my angular living in my rails asset pipeline.
The code that we end up with in application_controller.rb is as follows:
class ApplicationController < ActionController::Base protect_from_forgery after_filter :set_csrf_cookie_for_ng def set_csrf_cookie_for_ng cookies['XSRF-TOKEN'] = form_authenticity_token if protect_against_forgery? end protected def verified_request? super || form_authenticity_token == request.headers['X_XSRF_TOKEN'] end end
If you’re on rails 4, you the verified_request? line needs hyphens, not underscores:
super || form_authenticity_token == request.headers['X-XSRF-TOKEN']
We can check if this is working in the following way. In our sample app, before this code is implemented, we can go to the club or team entity, and press the delete button. We’ll see on our rails server console a message WARNING: Can't verify CSRF token authenticity
. In production this transaction would actually reject, in dev and test CSRF protection is turned down to only a warning, as the rspec test cases have difficulty providing the tokens correctly. Our aim is for this message to go away.
Implement the code snippet into your application_controller, and restart your rails server (I’m not 100% you have to restart, but I think you do). Then refresh your browser, and look at the network traffic monitor (if you’re on Chrome) to see that the get transaction now sets an XSRF-TOKEN cookie. Hit the delete button, and you’ll see that your rails server no longer complains about CSRF token authenticity.
Update:
Since I wrote this there have been some extensions.
1. There is now a gem available that is based on this discussion above https://github.com/jsanders/angular_rails_csrf, provided by jsanders.
2. I’ve written a more elaborate post, dealing with issues relating to Devise, multithreading, and the newer Rails 4 behaviour.
Pingback: AngularJS and Rails CRUD application using ng-boilerplate and twitter bootstrap: Tutorial Index | technpol
Pingback: Rails app for Angularjs, building the rails league application: part 1 | technpol
Pingback: AngularJS and Rails Tutorial: part 7 form error handling, datepicker | technpol
Pingback: JSON / JSONP XSS vulnerability with AngularJS and Rails | technpol
What about for rails 4? I added the code and the server still replies with “Can’t verify CSRF token authenticity”. Then I tried adding “.config([“$httpProvider”, function(provider) {
provider.defaults.headers.common[‘X-CSRF-Token’] = $(‘meta[name=csrf-token]’).attr(‘content’);
}]);” and it still doesn’t work. 😦
(I added that to app.js)
Unfortunately I haven’t got to rails 4 yet, so I don’t have a great answer for you. I wasn’t aware that CSRF processing had changed, so I guess I have that to look forward too!!
Pingback: 6: Adding ngGrid and an edit page, and CSRF protection | technpol
Thanks for the article! I made a gem that automatically adds support for this scheme to your application: https://github.com/jsanders/angular_rails_csrf. Hope it’s useful to some people!
That looks very cool jsanders. I wonder if it’s worth dealing with the JSON/JSONP vulnerability at the same time? https://technpol.wordpress.com/2013/09/28/json-jsonp-xss-vulnerability-with-angularjs-and-rails/
Pingback: Rails4, AngularJS, CSRF and Devise | technpol
Great blog you have here but I was wanting to know if you knew of any forums that cover the same topics discussed here?
I’d really like to be a part of online community where I can get
comments from other experienced individuals that share the same interest.
If you have any suggestions, please let me know. Bless you!
Manie: I haven’t really found any as yet. There are some angularJS forums and blogs, and obviously the rails github itself. But I haven’t been particularly active in forums.
I am facing some problems related to http://stackoverflow.com/questions/25743627/ruby-on-rails-angularjs-session-getting-reset
Please see if you can help regarding this.