27

I'm interested in hearing what approaches people have taken when building a RESTful (or quasi-RESTful) API for their web applications.

A practical example:

Say you have a traditional browser-based web application which uses CSRF protection on all forms. A hidden input with a CSRF protection token is included in each form presented in the browser. Upon submission of the form, if this input does not match the server-side version of token, the form is considered invalid.

Now say you want to expose the web application as an API (perhaps using JSON instead of HTML). Traditionally when publishing an API, I've considered transactions to be unilateral (meaning the API consumer builds the request based on the published API instead of first requesting a form and then building a request using the returned form).

The "unilateral" approach breaks down when things like CSRF protection factor in. The CSRF protection token needs to be included in any POSTS/PUTS/DELETES sent by the API consumer.

I've been trying to think of how best to address this. Requesting a form each time an API call needs to be made seems very awkward (especially when dealing with asynchronous operations), but all other alternatives I've thought of on my own seem to defeat the CSRF protection (or at least punch holes in it), which is unacceptable.

Do any of you have insight into this?

Thanks.

(Not that it should matter too much, as the issue is conceptual and platform agnostic, but I'm dealing with a traditional LAMP stack and use Symfony 1.4 as my application framework. My goal is to publish a JSON-format web API allowing developers to make mobile/desktop apps that play nice with an existing web application.)

ʇsәɹoɈ
  • 22,757
  • 7
  • 55
  • 61
Darryl H. Thomas
  • 1,021
  • 9
  • 13

1 Answers1

2

REST goes quite well with authentication (i.e. Basic Authentication), so try using username of your user site's and password specific to an application bound to that user -- technique sometimes called API keys. Something that FriendFeed's API is doing see the documentation.

Few notes tough:

  • use digest authentication or SSL
  • having API key's per application can be a bit of an overhead, so most sites have single API key for all 3rd party applications
  • OAuth might be worth checking out
Zoran Regvart
  • 4,630
  • 22
  • 35
  • Thanks for your response. As it stands today, the API will indeed use HTTP authentication, but my concern is that this alone cannot solve the CSRF problem (if the app doesn't require CSRF protection when credentials have been included, this could be exploited via other user agents that use HTTP auth...an authenticated RSS/ATOM feed, for example). I'll definitely look more closely at how an API key might help this issue, but at first glance I don't think it solves the core problem. Thanks again for your help. – Darryl H. Thomas Feb 15 '10 at 17:55
  • 1
    Think of it this way: CSRF is a problem if another (malicious) web site can reproduce/imitate the request as if it came from a valid source (in your case 3rd party application), if you use HTTP Authentication that came from the browser prompt that would be a problem (the browser will cache the authentication and repeat it in the Authorization header on subsequent requests); but 3rd party requests that came from AJAX/standalone clients have to place the Authorization header themselves in the request, and when doing so browser will not cache/repeat the header -- preventing malicious CSRF's. – Zoran Regvart Feb 15 '10 at 18:50
  • Yeah, I think we're on the same page. I'd hoped to avoid an API key due to the target audience, but this may indeed be the way to go. Still considering the "request a form for each request" approach, but I'm really not fond of that. Thanks again. – Darryl H. Thomas Feb 15 '10 at 19:08
  • How would an api key secure calls made by a javascript web application? It seems to me that anyone could examine the javascript of a legitimate application and steal its api key. – ʇsәɹoɈ Feb 25 '11 at 22:25
  • Your api keys should be unique to individual user (and potentially 3rd party application); but yes, the security of api keys relies on the fact that they are confidential between the site offering the service and the 3rd party application -- much in the same way http session ids are; for greater security you should look into OAuth. – Zoran Regvart Feb 28 '11 at 08:42
  • I have the same issue as @DarrylH.Thomas However, I do not quite see why OAuth resolves this issue. OAuth, I believe, requires requests to be sent with an access_token, client_id and client_secret. so if there is a man in the middle that sniffs out these 3 parameters, they can still setup a CSRF form. The idea is because the access token has a time limit, so you make it harder. And the API key allows you to turn off web service access to individual apps that got targeted. Ideally should implement OAuth with HTTPS. Am I right? – Kim Stacks Jun 12 '12 at 14:57
  • 2
    @kimsia Yes you are: CSRF are special kind of unauthenticated invocations where a page loaded in the browser has authenticated access to another page (usually via session cookies which are shared throughout the browser). If you're using OAuth for autentication the OAuth parameters are known only to the authorized browser page, so other page cannot take advantage of shared browser state. And yes, if you need to prevent CSRF and MITM you need to be using SSL. – Zoran Regvart Jun 18 '12 at 13:34
  • 1
    "*3rd party requests that came from AJAX/standalone clients have to place the Authorization header themselves in the request*": that's not true if it comes from the same browser, but a different page, which is exactly the problem with CSRF. (A malicious request could be an auto-submitted form, for example.) XHR requests also send the Basic/Digest auth headers automatically. SSL doesn't prevent CSRF either. – Bruno Jul 12 '13 at 00:15