Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rails - InvalidAuthenticityToken for json/xml requests

Tags:

For some reason I'm getting an InvalidAuthenticityToken when making post requests to my application when using json or xml. My understanding is that rails should require an authenticity token only for html or js requests, and thus I shouldn't be encountering this error. The only solution I've found thus far is disabling protect_from_forgery for any action I'd like to access through the API, but this isn't ideal for obvious reasons. Thoughts?

    def create     respond_to do |format|         format.html         format.json{             render :json => Object.create(:user => @current_user, :foo => params[:foo], :bar => params[:bar])         }         format.xml{             render :xml => Object.create(:user => @current_user, :foo => params[:foo], :bar => params[:bar])         }     end end 

and this is what I get in the logs whenever I pass a request to the action:

 Processing FooController#create to json (for 127.0.0.1 at 2009-08-07 11:52:33) [POST]  Parameters: {"foo"=>"1", "api_key"=>"44a895ca30e95a3206f961fcd56011d364dff78e", "bar"=>"202"}  ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):   thin (1.2.2) lib/thin/connection.rb:76:in `pre_process'   thin (1.2.2) lib/thin/connection.rb:74:in `catch'   thin (1.2.2) lib/thin/connection.rb:74:in `pre_process'   thin (1.2.2) lib/thin/connection.rb:57:in `process'   thin (1.2.2) lib/thin/connection.rb:42:in `receive_data'   eventmachine (0.12.8) lib/eventmachine.rb:242:in `run_machine'   eventmachine (0.12.8) lib/eventmachine.rb:242:in `run'   thin (1.2.2) lib/thin/backends/base.rb:57:in `start'   thin (1.2.2) lib/thin/server.rb:156:in `start'   thin (1.2.2) lib/thin/controllers/controller.rb:80:in `start'   thin (1.2.2) lib/thin/runner.rb:174:in `send'   thin (1.2.2) lib/thin/runner.rb:174:in `run_command'   thin (1.2.2) lib/thin/runner.rb:140:in `run!'   thin (1.2.2) bin/thin:6   /opt/local/bin/thin:19:in `load'   /opt/local/bin/thin:19 
like image 848
Optimate Avatar asked Aug 07 '09 16:08

Optimate


1 Answers

With protect_from_forgery enabled, Rails requires an authenticity token for any non-GET requests. Rails will automatically include the authenticity token in forms created with the form helpers or links created with the AJAX helpers--so in normal cases, you won't have to think about it.

If you're not using the built-in Rails form or AJAX helpers (maybe you're doing unobstrusive JS or using a JS MVC framework), you'll have to set the token yourself on the client side and send it along with your data when submitting a POST request. You'd put a line like this in the <head> of your layout:

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

Then your AJAX function would post the token with your other data (example with jQuery):

$.post(url, {     id: theId,     authenticity_token: window._token }); 
like image 171
andrewle Avatar answered Nov 11 '22 10:11

andrewle