Hi, I'm Alex

I study Software Engineering at McGill.
I like pretty things and sometimes I make stuff.

Forgery Protection Strategy

May 06, 2013

I was pretty puzzled when I started a new Rails 4 app a week ago. I wanted to have a controller authenticate with Devise's token authentication and respond to JSON requests. I kept running into an ActionController::InvalidAuthenticityToken exception.

Having already done something similar in Rails 3, I guessed that it had something to do with the move to Rails 4. After searching for anything that had to do with the Authenticity Token and Rails 4 I came up empty. At this point I decided to dive into the Rails source to see what was actually going on when that exception was raised.

It turns out that there was a change made to the way missing authenticity tokens are handled in Rails 4. In a Rails 3 app, you'll notice that in the ApplicationController that gets generated along with the application you have a line that says protect_from_forgery. Looking at the source for that method, you'll see how Rails will protect your application from requests that are missing Authenticity Tokens.

def protect_from_forgery(options = {})
  self.request_forgery_protection_token ||= :authenticity_token
  prepend_before_filter :verify_authenticity_token, options
end

This method will ensure that verify_authenticity_token gets called before each action. If we take a look at this method now we see that the code that actually handles unverified requests (not surprisingly) is found in the handle_unverified_request method.

def handle_unverified_request
  reset_session
end

handle_unverified_request just resets the session when it's called. That's why there's no exception when using Rails 3. Let's take a look at the same method in the Rails 4 source. This time the method is a little different.

def handle_unverified_request
  forgery_protection_strategy.new(self).handle_unverified_request
end

What's this forgery_protection_strategy thing? Let's back up a little bit. When generating a Rails 4 application, the ApplicationController now passes a parameter to protect_from_forgery.

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception
end

Rails 4 lets you choose between three forgery protection strategies. When the application is generated, the default strategy is set to :exception which corresponds to ProtectionMethods::Exception.

class Exception
  def initialize(controller)
    @controller = controller
  end

  def handle_unverified_request
    raise ActionController::InvalidAuthenticityToken
  end
end

When calling protect_from_forgery with: :exception, Rails will set forgery_protection_strategy to the appropriate strategy. Then, when an unverified request is made, the handle_unverified_request method will delegate the responsibility to the appropriate strategy.

In the Rails 4 ApplicationController there's a comment that tells you to use the :null_session strategy if you're building an API. This strategy empties the session instead of raising an exception which is perfect for an API.

Let's Make a Bar Chart

March 18, 2013

A few days ago I started taking a closer look at Michael Bostock's D3.js. D3 is an amazing JavaScript library for mapping data to HTML elements or SVG nodes. I started off making some bar charts with HTML elements and then moved onto SVG nodes and transitions.

Generally, to make simple charts, all you need to do is follow these steps:

  1. Select the place you want to put your chart
  2. Select all the chart components
  3. Apply the data to this selection
  4. Add a new compononent for each piece of data that wasn't applied
  5. Position the new components
  6. Apply any other attributes or styles

Here's an example of a bar chart and the code that will create it below:

var data = [ 1, 2, 3, 4, 5, 4, 3, 4, 3, 2, 1 ];

var svg1 = d3.select('#barchart1')
             .append('svg')
             .attr('width', 240)
             .attr('height', 100);

svg1.selectAll('rect')
    .data(data)
    .enter()
    .append('rect')
      .attr('x', function(d, i) { return i * 22; })
      .attr('y', function(d) { return 100 - d * 20; })
      .attr('width', 20)
      .attr('height', function(d) { return d * 20; });

When setting an attribute, the second argument can be a literal, variable, or a function. The function can take up to two arguments: the value of the current piece of data and its index in the selection being operated on. With functions, it's possible to return a value based on what position the data holds. This can be useful when setting a position where every subsequent element will be offset by a larger value than the last. Using functions is also the only way to get a hold of a variable containing the value of the data.

D3 also lets you apply transitions to selections. For example, the bars in the bar chart can start off with a height of 0 and grow upwards.

var svg2 = d3.select('#barchart2')
             .append('svg')
             .attr('width', 240)
             .attr('height', 100);

svg2.selectAll('rect')
    .data(data)
    .enter()
    .append('rect')
      .attr('x', function(d, i) { return i * 22; })
      .attr('y', 100)
      .attr('width', 20)
      .attr('height', 0)
      .transition()
      .delay(function(d, i) { return i * 100; })
      .duration(200)
      .attr('y', function(d) { return 100 - d * 20; })
      .attr('height', function(d) { return d * 20; });

Transitions are simple: append a call to transition() and set the delay and/or duration with calls to delay and duration. Then, any attributes changed after the call to transition() will transition to their new values.

D3 can do so much more than just displaying bar charts or line graphs. Here's an amazing show reel with loads of great transitions and here's a bunch D3 examples.

Note that I've applied some default styles for SVG and rect in my stylesheet so that they appear centered and have a nice color. The default fill for SVG nodes is black.