title: Rails 4 skipping protect_from_forgery for API actions
body: <p>I've been implementing a Rails 4 application with an API. I want to be able to call the API from mobile phones and the webapp itself. I came across <a href="http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html" rel="noreferrer">this note</a> while researching <code>protect_from_forgery</code>:</p>
  
  <blockquote>
    <p>It's important to remember that XML or JSON requests are also affected and if you're building an API you'll need something like:</p>
  </blockquote>
  
  <pre><code>class ApplicationController &lt; ActionController::Base
    protect_from_forgery
    skip_before_action :verify_authenticity_token, if: :json_request?
  
    protected
  
    def json_request?
      request.format.json?
    end
  end
  </code></pre>
  
  <p>I was thinking of doing this, but I have some reservations/questions:</p>
  
  <ol>
  <li>This solution seems to leave the CSRF hole open because now an attacker could craft a link with an <code>onclick</code> javascript that posts JSON?</li>
  <li>Would checking for an API token be a reasonable substitute? i.e., what if instead of skipping the authenticity check, allowing it to fail the check and recover in <code>handle_unverified_request</code> if the api token is present and correct for current user?</li>
  <li>Or maybe I should just make the webapp and mobile devices <a href="https://stackoverflow.com/questions/7203304/warning-cant-verify-csrf-token-authenticity-rails">send the CSRF token in the HTTP headers</a>? Is that safe? How would the mobile phone even obtain the CSRF token, given that it isn't rendering HTML forms to begin with?</li>
  </ol>
  
  <p><strong>Edit for clarification:</strong></p>
  
  <p>I am more concerned about the webapp user clicking a crafted CSRF link. The mobile users are authenticated, authorized, an have an API key, so I am not concerned about them. But by enabling CSRF protection for the webapp users, the mobile users are blocked from using the protected API. I want to know the correct strategy for handling this, and I don't believe the Rails documentation gives the right answer.</p>