MooTools and Rails CSRF Protection

Wow! This takes me back! Please check the date this post was authored, as it may no longer be relevant in a modern context.

“Cross site request forgery” is also known as CSRF, XSRF or just request forgery (more at wikipedia and It’s a method of attack toward web applications- Rails 2.0 introduced a defence and Rails 2.1 enabled that defence by default. Call form_for…

<% form_for @friend, :action => 'create' do |f| %>

and Rails spits out more than just the form, it also generates a secret authenticity_token:

<form action="/friends" method="post">
<div style="margin:0;padding:0">
  <input name="authenticity_token" type="hidden" value="e8c827c47577e013cc4c06a99cab63da95b71915" />

AJAX submission of this particular form will include the authenticity token. So here’s the rub: what if the form is generated by something else?

new Element('form', { 'action': '/friends'});

Or what if there is no form?!

new Request.Json( ... ).post();

In these cases Rails would raise an ActionController::InvalidAuthenticityToken exception. To avoid an exception the CSRF check can be altogether disabled for a controller:

skip_before_filter :verify_authenticity_token

Of course this is a compromise between convenience and security. For those who want security and AJAXy goodness (well, with MooTools at least), there is a better way.

Using AuthenticityToken with MooTools

MooTools has a wonderful object oriented codebase. First Rails needs to pass the authenticity_token into Javascript, then we can use the inheritance from MooTools to pass the authenticity_token with every request.

The authenticity_token can be passed in the header of the Rails application layout. It’s just one line:

<%= javascript_tag "const AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? %>

And now pass that token with every POST request (GET requests don’t check CSRF):

// Include authenticity_token in Request.JSON fires
// move the send function
Request.prototype._send = Request.prototype.send

  auth_token: function(){
    return AUTH_TOKEN;

  // This is more verbose than is ideal, but I don't see a better place
  // to hook this functionality in
  send: function(options){
    var type = $type(options);
    if (type == 'string' || type == 'element') options = {data: options};

    var old = this.options;
    options = $extend({data:, url: old.url, method: old.method}, options);

    switch ($type({
      case 'element': = $(; break;
      case 'object': case 'hash': = Hash.toQueryString(;

    // If this isn't a get request add the authenticity_token
    if (options.method != 'get' || options.method != 'GET') ='&authenticity_token='+this.auth_token();

    // Call the original send


Look at that, now every AJAX call from MooTools will attach our CSRF. All the ease of normal javascript, all the security of the native Rails defences.