10

I have been playing around with using rest-client to access a rails app I have written. I've written a quick script to log in and make a post request. Everything is working but I did have to work round the fact that no authenticity_token is served if you make a request for a form in json. I had to make a regular html request in other get the authenticity_token and then included this in the json I submitted as part of my post request. Basically I have a quick an dirty script like the one below

private_resource = RestClient::Resource.new( 'https://mysite.com')

params =  {:user => {:email => '[email protected]', :password => 'please'}}
#log in
login_response = private_resource['users/sign_in'].post(params, :content_type => :json, :accept => :json)
#get cookie
cookie = login_response.cookies
#get json  
json_response = private_resource['products/new'].get(:content_type => :json, :accept => :json, :cookies => cookie)
#another request that returns html form with authenticity token 
response_with_token = private_resource['products/new'].get( :cookies => cookie)
#extract token 
token = Nokogiri::XML(response_with_token).css('input[name=authenticity_token]').first.attr('value')
#update cookie
cookie = response_with_token.cookies
#populate form and insert token
form = JSON.parse(json_response)
form['name'] = "my product"
form['authenticity_token'] = token
#submit the request
private_resource['products'].post(form.to_json, {:cookies => cookie, :content_type => :json, :accept => :json})

There is the option to turn off CSRF protection for json requests but I would rather not do that. I could go the mechanize route or something similar and then I wouldn't worry about json requests with CSRF but I just wanted to play around with doing this stuff with rest-client

I guess I'm just curious to know if there is a reason why no authenticity_token is served for json requests and I'm also wondering if there is a better way of solving the token problem than the pretty hacky approach I've taken here

2 Answers 2

9

Put the below code into your application controller :

def verified_request?
    if request.content_type == "application/json"
      true
    else
      super()
    end
end

And call this method using before_filter .

For more details check : http://blog.technopathllc.com/2011/09/rails-31-csrf-token-authenticity-for.html

And check this issue in rails : https://github.com/rails/rails/issues/3041

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your reply swati, it looks useful. I guess though I was trying to avoid just turning off the CSRF checks. It just seems a little strange to me that rails serves json forms that don't contain any token but then checks for a token. Would it make sense just to serve the json forms with a token included rather than switching off the checks for json content?
welcome ... yes that's only way to by-pass the CSRF token issue . If you want to pass token with your JSON request, you can use header like : headers: { 'X-CSRF-Token': '<%= form_authenticity_token.to_s %>' }
2

In your app/views/products/new.json.jbuilder, add this:

json.authenticity_token form_authenticity_token

This will insert a key "authenticity_token" with value being the token, so in your json_response you get the token as well. Idea from this answer.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.