Description
This is a continuation of the discussion at #57
Consider a modern stack where there is a frontend application that is completely decoupled from the API server.
The cookies are still saved in the browser on the API server, and they are sent with the request if "withCredentials" flag are set. So far, so good. (Maybe we should add some documentation regarding that too, setting ALLOW_CREDENTIALS server side should be coupled with setting withCredentials flag in the JS requests.)
CSRF and CORS are at somewhat odds though, since one is about preventing cross site requests that come from unauthorized sources, whereas the other is a mechanism for accepting requests coming from authorized sources.
When CORS is enabled via this library, there are currently no recommendations on how to deal with this however. By default, even if a cross site is added to the whitelist, and potentially unsafe methods like POST, PUT are allowed (already enabled by default), the API server will reject incoming POST requests due to missing CSRF token data.
There are a few different approaches that could be suggested:
1- Since we are explicitly allowing a cross-site request, we can suggest the user to disable CSRF on those endpoints. However, CSRF protection should only be disabled if the request is coming from a whitelisted origin. Can we just check the Origin header there? AFAIK Origin header cannot be faked in a browser setting.
2- We could also suggest that the user disabled CSRF protection when the content type is JSON. This has a caveat mentioned here:
Just an FYI, Flash allows setting the Content-Type for cross-origin requests as shown here: http://saynotolinux.com/tests/flash-contenttype.html . You still need a CSRF token or custom header even if your endpoint requires a Content-Type of 'application/json'.
http://homakov.blogspot.com.tr/2012/06/x-www-form-urlencoded-vs-json-pros-and.html
There the OP originally suggested we can leave off CSRF token when we do this, but says he changed his mind afterwards. Not sure what his current stance is. /cc @homakov Could you give a recommendation here?
3- We could suggest the user to expose a /csrf endpoint. This endpoint will be hit by the cross-site before any POST request (once when the site is loaded, or everytime before a POST request). Then, the subsequent POST request should send this csrf token via a csrf header (X-CSRF). This /csrf endpoint should be protected against cross origin requests from other sites, otherwise a malicious site can similarly retrieve the token via AJAX, and send that with the POST data.
4- There might be some discussion of old vs modern browsers regarding CSRF and CORS.