Module: ActionController::RequestForgeryProtection::ClassMethods

Defined in:
lib/action_controller/request_forgery_protection.rb

Overview

Protecting controller actions from CSRF attacks by ensuring that all forms are coming from the current web application, not a forged link from another site, is done by embedding a token based on the session (which an attacker wouldn't know) in all forms and Ajax requests generated by Rails and then verifying the authenticity of that token in the controller. Only HTML/JavaScript requests are checked, so this will not protect your XML API (presumably you'll have a different authentication scheme there anyway). Also, GET requests are not protected as these should be idempotent anyway.

This is turned on with the protect_from_forgery method, which will check the token and raise an ActionController::InvalidAuthenticityToken if it doesn't match what was expected. You can customize the error message in production by editing public/422.html. A call to this method in ApplicationController is generated by default in post-Rails 2.0 applications.

The token parameter is named authenticity_token by default. If you are generating an HTML form manually (without the use of Rails' form_for, form_tag or other helpers), you have to include a hidden field named like that and set its value to what is returned by form_authenticity_token. Same applies to manually constructed Ajax requests. To make the token available through a global variable to scripts on a certain page, you could add something like this to a view:

<%= javascript_tag "window._token = '#{form_authenticity_token}'" %>

Request forgery protection is disabled by default in test environment. If you are upgrading from Rails 1.x, add this to config/environments/test.rb:

# Disable request forgery protection in test environment
config.action_controller.allow_forgery_protection = false

Learn more about CSRF (Cross-Site Request Forgery) attacks

Here are some resources:

Keep in mind, this is NOT a silver-bullet, plug 'n' play, warm security blanket for your rails application. There are a few guidelines you should follow:

Instance Method Summary collapse

Instance Method Details

#protect_from_forgery(options = {}) ⇒ Object

Turn on request forgery protection. Bear in mind that only non-GET, HTML/JavaScript requests are checked.

Example:

class FooController < ApplicationController
  # uses the cookie session store (then you don't need a separate :secret)
  protect_from_forgery :except => :index

  # uses one of the other session stores that uses a session_id value.
  protect_from_forgery :secret => 'my-little-pony', :except => :index

  # you can disable csrf protection on controller-by-controller basis:
  skip_before_filter :verify_authenticity_token
end

Valid Options:

  • :only/:except - Passed to the before_filter call. Set which actions are verified.

  • :secret - Custom salt used to generate the form_authenticity_token. Leave this off if you are using the cookie session store.

  • :digest - Message digest used for hashing. Defaults to 'SHA1'.


76
77
78
79
80
# File 'lib/action_controller/request_forgery_protection.rb', line 76

def protect_from_forgery(options = {})
  self.request_forgery_protection_token ||= :authenticity_token
  before_filter :verify_authenticity_token, :only => options.delete(:only), :except => options.delete(:except)
  request_forgery_protection_options.update(options)
end