11

I'm developing RESTful API using php/symfony2.

Symfony2 comes with CSRF protection out of the box and it works fine when using normal form data (it passes CSRF token to the form and when posted back it expects the same token which is embeded in the form).

Nonetheless this solution is not fit for purpose if you develop RESTful API, where my communication between backend<->frontend is purely JSON based. Because of that I disabled CSRF.

I'm aware not having CSRF token is not safe, so I'm wondering what's the most optimal way to have CSRF with RESTful API.

One idea in mind is to have specific URL e.g. /api/generate/csrf, which can be called by frontend then append token to json request. It doesn't sound as the safest way as token technically could be generated by anyone.

What's the best way to approach CSRF problem when developing RESTful APIs.

Cheers, Richard

ono2012
  • 4,967
  • 2
  • 33
  • 42
richard.pi
  • 111
  • 1
  • 4
  • 1
    What's the client you're now using for the API? Is this another web service, a mobile app or a frontend client (like angular/backbone/ember). If you use the first or second option, answers can be completely different than the last option. – Jurian Sluiman Jan 22 '14 at 14:39
  • @Jurian Sluiman The client (frontend) is web based (html5/js) at the moment. However there might be a need to support other devices in the future as well, so I don't want to limit myself to web. – richard.pi Jan 22 '14 at 14:58

2 Answers2

1

Remember that you only need CSRF protection when your REST client is using session based authentication, otherwise CSRF protection won't help you.

If your requests DO use session based authentication, I would include the CSRF token as a header. Something like:

CSRF-Token: dfsa0jr3n2io20a;
gitaarik
  • 42,736
  • 12
  • 98
  • 105
  • unfortunately REST client is using session based authentication (i know it's not perfect, but that's how it is at the moment). i understand there are ways of passing CSRF token as header, but how do i get one? is getting one by calling e.g. /api/give/me/token a safe bet? – richard.pi Jan 22 '14 at 15:29
  • You should generate the CSRF token on the server and put it in the page. Then when the client does a request with that token you are sure that the request came from that page. That's the idea. Frameworks like Symfony do this automatically for you for Forms, but you have a little bit of a special case over here so you should implement it yourself. – gitaarik Jan 22 '14 at 16:04
  • all the data is which is passed from the client is as json. backend doesn't generate any forms for the frontend in this instance. i know i could create a special call e.g. /api/token, which would be returning token, which then i can append to json, which will be send to the server. the problem with this solution is that a potential attacker also could access /api/token to generate token and add to attacker's fake json request – richard.pi Jan 22 '14 at 16:29
  • You shouldn't get the token through a separate request, you should include the token in the page where you execute the API call, so that the API call can send this token back again. – gitaarik Jan 23 '14 at 08:42
  • so how do i get the token in the page? as i said before the form is not rendered by backend. form is send as json by frontend (totally separate from the api-backend) – richard.pi Jan 23 '14 at 09:21
  • Well, I just explained, you should include the token in the page where you execute the API call. What don't you understand about that? – gitaarik Jan 23 '14 at 09:52
  • From what I see.. the page that calls the API is not generated in any way by the APi so a token couldn't be added and then, when a REST call is made, the connection is made to the server (that being the first call, so not capable of have any kind of APi generated token). How could you use a CSRF token in this respect? – qooplmao Jan 25 '14 at 02:46
  • I assume the frontend that makes the API call is a webapp which is generated by the server. Then the server can include a CSRF token in the webapp. – gitaarik Jan 25 '14 at 17:46
  • 1
    Qoop is right. the frontpage is NOT generated by the server. so, how do i obtain token? – richard.pi Jan 27 '14 at 10:54
  • Well, the frontpage is generated by some server in the end. If you want to use a CSRF token, that server will need to have this token. If the server is a different server from the server your API is located, you could create another API, which will be used to get tokens. This API should have authentication and should be called on the server side. But it might be easier to add authentication per request. – gitaarik Jan 27 '14 at 11:54
  • the frontend if fully generated by frontend framework (not touching server side), not by the server. i was thinking about using some matching algorithm on the frontend (generated by js or something), but i'm not sure if frontend generated token is a safe bet – richard.pi Jan 27 '14 at 13:42
0

I'm working on this issue too. Here is my original question.

I have a theoretical solution so far, but I'm not quite sure it will work. Maybe somebody can comment.

  1. Add the CSRF TOKEN to the API response cookie readable by the JS application;
  2. Send it with the request as X-CSRF-TOKEN header value by the JS application;
  3. Verify the CSRF TOKEN on the API.
tooleks
  • 557
  • 5
  • 17