Adding Csrf-Protection to your Rails-Backbone App

When integrating Backbone.js in your Rails App, you might face the problem of the inability to verify the CSRF-Token.

The CSRF Protection secures your app with a token. Rails makes sure that the person who is interacting with your app is someone who started a session in your site, not some random attacker from another site. So you should not turn it off, unless you know what you are doing.

For more information on this Topic, check out the Rails Security Guide.

This problem occurs as soon as you are trying to send form data, without the CSRF-Token provided by Rails.

Started POST "/products" for 127.0.0.1 at 2015-12-16 10:06:05 -0300
Processing by ProductsController#create as JSON
  Parameters: {"product"=>{"name"=>"foo"}}
WARNING: Can't verify CSRF token authenticity
...
Completed 302 Found in 7.6ms (ActiveRecord: 0.8ms)

After this request, Rails will terminate your session and you will have to login again.

This problem is caused by your Backbone.js application, which is sending the data directly to the backend without providing the CSRF-Token.

To solve this problem you need to add the token to your Backbone request. One of the simplest solutions I came across is the following by Anton Shuvalov.

// https://github.com/shuvalov-anton/backbone-rails-sync
Backbone._sync = Backbone.sync;
Backbone.sync = function(method, model, options) {
  if (!options.noCSRF) {
    var beforeSend = options.beforeSend;

    // Set X-CSRF-Token HTTP header
    options.beforeSend = function(xhr) {
      var token = $('meta[name="csrf-token"]').attr('content');
      if (token) { xhr.setRequestHeader('X-CSRF-Token', token); }
      if (beforeSend) { return beforeSend.apply(this, arguments); }
    };
  }
  return Backbone._sync(method, model, options);
};

It grabs the CSRF-Token provided in the meta tags of your Rails application and sets it for the request header field X-CSRF-Token.

After adding this to the Backbone code, it works as expected.

Started POST "/products" for 127.0.0.1 at 2015-12-16 10:08:29 -0300
Processing by ProductsController#create as JSON
  Parameters: {"product"=>{"name"=>"foo"}}
...
Completed 200 OK in 40.6ms (Views: 0.6ms | ActiveRecord: 10.3ms)
Read more »

How to interact with hidden elements with Protractor

The other day I was trying to interact with a hidden file input field:

<div class="col-sm-3">
  <input class="btn btn-default" class="hidden" accept=".csv"  id="geofence_file_input">
  <a class="btn btn-default" id="textbox-for-geofencefile">Select File</a>
  <span ng-if="LineItemForm.augmentations.geofence.file"></span>
</div>

And the CSS:

.hidden {
  display: none;
}

Which caused this problem:

Failed: Wait timed out after 100015ms

Workarounds include displaying it, interacting with it, hiding it again, which I didn't like.

Read more »

Time and Material

As of 2016, we will no longer work with clients on fixed bid projects. They are not a good fit for us and we are not a good fit for them.

All of our clients are startups. Fixed bids are counterproductive for startups. They give the client a false sense of security and they punish changing requirements.

Fixed bids make clients think that their project will be finished in a fixed period of time if their requirements don't change while developing the project. That is a big if!

Read more »

The 7 Days Open Source Challenge

Last Wednesday I gave a lightning talk about open source at the Buenos Aires Ruby Meetup. I proposed a challenge to all attendees: Contribute to one (or many) open source projects for 7 days straight.

The rules are simple:

  • You have to do it for 7 days straight
  • If you can't do it one day, that breaks your streak
  • When you break your streak, you have to start over from day 1
Read more »

Why using default_scope is a bad idea

default_scope is a method provided by ActiveRecord, which allows you to set a default scope (as its name implies) for all operations done on a given model. It can be useful for allowing soft-deletion in your models, by having a deleted_on column on your model and setting the default scope to deleted_on: nil

Read more »

The Lean Startup Way

At OmbuLabs we like to split our time working on our own products, client projects, and open source code. We have embraced the Lean Startup methodology not only for our own products but also for our client projects.

It is easier to apply the methodology to our own products than to our client projects. With our products, we decide what goals we want to reach and what experiments we are going to run to validate our hypotheses.

Read more »

How to Git push with blocked ports

Often times I find myself working out of a coffee shop with a terrible Internet connection. We have a nice office at OmbuLabs but there is still that Je ne sais quoi at coffee shops.

The cool thing about Git is that you can git commit all your changes while enjoying a cup of coffee and git push later (when you're back at home with a decent connection)

But what if you want to git push from the coffee shop? Sometimes the only ports that are open are port 80 (HTTP) and 443 (HTTPS).

Read more »

Enumerable#grep vs Enumerable#select

Often, Enumerable#select is the chosen method to obtain elements from an Array for a given block. Without thinking twice, we may be doing more work than necessary by not taking advantage of another method from the Enumerable module, Enumerable#grep.

Read more »

Almundo's Bill Vulnerability

The other day my friend Juan Rossi reported a vulnerability in the Almundo billing system. Since then, the vulnerability has been fixed by Superfactura, their billing software provider.

Almundo is one of the biggest travel agencies in Argentina. Their site is among the 250 most visited websites in the country.

The vulnerability allowed anyone to download billing information about their clients by creating a pretty simple HTTP GET request. No programming knowledge required.

Read more »