Liquid Media's Apps

form_authenticity_token in functional tests

I was working on a functional test when I got this error:

  1) Error:
test_get_structure(Admin::DmutoolControllerTest):
ActionView::TemplateError: No :secret given to the #protect_from_forgery call.
Set that or use a session store capable of generating its own keys (Cookie Session Store).
    On line #142 of admin/dmutool/structure.html.erb

    139:   <input type="submit" id="structure_form_submit" value="Process Structural Changes" />
    140:   <input type="button" id="structure_form_finished" value="Finished with Structural Changes" />
    141:   <input type="hidden" name="structure_form_changes" id="structure_form_changes" value="" />
    142:   <input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>" />
    143:   <!-- start render_components -->
    144:   <%= render_components @dc %>
    145:   <!-- end render_components -->

A quick Google took me to this page where the author explains that the problem is because forgery protection is turned off by default in testing. His solution is to adjust the view:

<% if protect_against_forgery? %> 
<div id="authenticity_token"><%= form_authenticity_token %></div> 
<% end %> 

I don't like this approach because it requires you to add an if statement around every form_authenticity_token helper call. I came up with a much simpler way. Add the following to your test_helper.rb file:

# Request Forgery Protection hack
# form_authenticity_token causes an error in test mode because protect_against_forgery is turned off.
module ActionController
  module RequestForgeryProtection
    def form_authenticity_token
      return "form_authenticity_token OVERRIDE!"
    end
  end
end

Now the method will no longer raise an exception.

There are some risks with this — specifically you can't test any behaviour that depends on forgery protection. It could also cause subtle problems in tests, but my test suite ran cleanly.

Tagged protect_from_forgery, rails, and security.
blog comments powered by Disqus