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 this note while researching
Sending the CSRF token in an HTTP header is indeed a common approach. It ensures that the client has somehow obtained a valid token. For example, a crafted CSRF link will be sent with credential cookies but the header will not include the CSRF token. Your own javascript on the client will have access to domain cookies and will be able to copy the token from a cookie to the header on all XHR requests.
AngularJS follows this approach, as explained here.
As for your first two questions:
- This solution seems to leave the CSRF hole open...
Indeed, which is why you should not disable the CSRF token also in your API.
- Would checking for an API token be a reasonable substitute? ...
Probably not. Take into consideration the following (from OWASP):
CSRF tokens in GET requests are potentially leaked at several locations: browser history, HTTP log files, network appliances that make a point to log the first line of an HTTP request, and Referer headers if the protected site links to an external site.
General recommendation: Don't try to invent the wheel. OWASP has a page called REST Security Cheat Sheet as well as the one I linked to before. You can follow the Angular approach (copying the token from a cookie to a header on each XHR request) and for regular non-ajax forms, be sure to use only POST and a hidden field as is normally done in CSRF protection of static server forms.