Rails session + CSRF token + jQuery ajaxPrefilter

Ruby on Rails has security to protect session, to protect from forgery and session hijacking.

Here's what happens in a typical Rails app:

Recently hackers have attacked via AJAX, so Rails recently added similar protection for AJAX.

In parallel, jQuery recently added the new ajaxPrefilter chain, which makes it possible for developers to add Rails security for AJAX connections.

What is a secure token?

A secure token in this context is a long string of random characters. The string must be web safe because the string may appear within a web page, or a URI.

The token is typically put on the page in one or more ways.

If the token is in the page header, but not in the form, then there must be Javascript in the form that looks up the meta tag and gets the token.

jQuery token examples

To look up the token using jQuery, we use code like this:

  csrf = $('meta[name=csrf]').attr('content'),

To add the token to an AJAX request on the fly, we use jQuery ajaxPrefilter:

  http://api.jquery.com/jQuery.ajaxPrefilter/

The jQuery ajaxPrefilter is new in jQuery 1.5. Some older blog posts describe ways to accomplish much the same goal by using jQuery beforeSend, or jQuery ajaxSend.

More on Rails tokens

Rails provides much of the infrastructure for tokens, so if you're interested in learning more here are key tems:

Rails with HTTP GET and HTTP PUT

The Rails built-in commands do tokens for HTTP POST requests, but not for HTTP GET requests. This is because the Rails developers say that HTTP GET requests do not change data, so are safer; i.e. if a hacker does session hijacking, then he would be able to see data, but not change data.

Our opinion is that HTTP GET should also be protected.

Mustache, Handlebars, and Liquid Markup

Rails provides the token dynamically. When we use markup languages like Mustache, Handlebars, and Liquid Markup, we provide the token to the markup engine.

Web safe strings and Base64 encoding

One way to make the token string web-safe is to use Base64 encoding. This is how Rails does it.

However, Base64 can sometimes use characters like the plus sign "+" which are interpreted differently within URIs: a plus sign get translated to a space, which is not what Base64 wants.

In our experience, it's more reliable and more universal to use strings that contain only letters and numbers, and no symbols.



What's Next?

blog comments powered by Disqus