Making a POST request to a Rails API Endpoint

Here's a rare super-technical blog post. I spent enough time struggling with this seemingly simple problem today, that I felt I should share the answer.

The problem: You're designing a REST API for your Rails app. You want to let people insert records in your application via a POST request. However they submit their POST request via their 3rd party application, and your app throws an InvalidAuthenticityToken exception. Why is this happening?

The background: Ruby on Rails stores an authenticity token for each session, and submits this token as a hidden form field in any POST request upon a form submission. It does this to authenticate that the request is actually coming as a form submission through the web site, as opposed to a random POST request generated from CURL or another tool. A 3rd party application developer certainly doesn't have a token assigned and therefore can't submit this via their API request.

The solution: Rails only checks for the authenticity token in the case of a form submission. If you submit your data as content-type application/xml or application/json, then the token is not required. As a result you can set the content type appropriately and encode your input parameters as either xml or json. See the below gist for a ruby example.

It was hard to find this solution via google. Anyone know a smoother solution? Does the API designer generally disable forgery protection in this scenario on POST endpoints for inserting data via an API? Let me know in the comments or on twitter @petkanics
  • Nathan Hurst

    To skip authenticity token verification in your Rails controller, you can addskip_before_filter :verify_authenticity_tokenAs far as API design… Rails uses the authenticity token to prevent CSRF/XSRF attacks, allowing only people who have seen a form on a page to submit that form (and preventing people from nefariously submitting a form with someone else’s session). In a stateless/sessionless API, you don’t have to worry about these kinds of attacks. As I’m sure you’re doing, API designers generally use some kind of API key to authenticate users

  • Doug Petkanics

    Ah, thanks for the comment Nathan. That looks like an easy enough solution for the API designer. But I guess it leads to this followup rails security question…Since you can bypass providing the authenticity token by changing the content type and parameter encoding, then couldn’t you perform a CSRF attack by injecting code which performed the above tactic within a POST request anyway? I guess it wouldn’t be a true CSRF since it would be detectable via the change in content type, however it could still have the desired effect of producing data side effects on the server. I’m not worried about this in the API case where you’re presumably doing key based authentication, but just in the general Rails RESTful application.

  • kondormit

    How can I add basic user authentication in request?

  • biomblog

    It is safe to remove csrf for API calls as the particular vulnerability can only be executed through a web browser.