views:

233

answers:

1

I am using REST and OAuth to talk to a Rails app (from an iPhone app, but that should not be relevant). However, I am running into some issues with Rails' CSRF protection (via protects_from_forgery).

I understand that CSRF protection only kicks in for regular form submissions (i.e. Content-Type=application/x-www-form-urlencoded), so I would be fine if I was submitting JSON or XML data. Unfortunately, OAuth is currently limited to application/x-www-form-urlencoded requests. There's a draft spec that extends OAuth to non-form-urlencoded data, but this doesn't help me right now.

The way I see it, I have the following options:

  1. Send the data as JSON, knowing that it would not be part of the OAuth signature and thus subject to man-in-the-middle attacks. Obviously not an attractive solution.

  2. Create special Rails actions (e.g. UsersController#update_oauth) that internally delegate to the regular actions (e.g. UsersController#update). Then exclude these from the forgery protection (protects_from_forgery :only => [:update]). This should work and might be borderline acceptable for one or two actions, but obviously would be a very messy solution.

  3. Override the Rails CSRF protection to ignore OAuth requests. I have not tried this, but it seems like it should be possible to change one of the hooks (perhaps the verify_authenticity_token filter) to consider OAuth requests successful.

Has anybody run into this before? Any recommendations? Or am I perhaps missing something basic?

+3  A: 

I'll answer my own question. :)

I added the following method to our OAuth controller extensions. The only thing this adds on top of the default implementation is the oauth? check. This seems to do the trick and feels like a pretty clean solution.

def verify_authenticity_token
  verified_request? || oauth? || raise(ActionController::InvalidAuthenticityToken)      
end
Mirko Froehlich