I realize that OWASP recommends CSRF tokens but I rarely see them used with public standalone HTTP APIs. This would seem to indicate that they’re not always necessary.
To make this a little more concrete, I would envision the following scenario:
The API server serves a limited number of frontends with an explicit CORS whitelist.
HTTP method semantics are followed religiously (no writes in GET).
All routes require authentication.
All POST routes require a request body.
All routes that take a request body require a JSON content-type header.
Cookies are httpOnly but not sameSite.
Based on my understanding of SOP setting a JSON content-type header on requests should trigger a preflight request which would fail for untrusted origins. If all POST routes require a JSON content-type header, that should then mean they’ll always fail the preflight, leaving only GET requests.
So this would not mitigate CSRF attacks against GET routes but as these can’t be used for exfiltration (as SOP prevents the response from being read) and the GET routes should not cause any data modification, guarding these requests with CSRF tokens would not appear to make a practical difference.
Given how viciously some people defend CSRF tokens, I can’t shake the feeling I’m overlooking an obvious problem here. I realize redundant protections may be valuable in their own right, but what I’m trying to understand is whether in the scenario described the CSRF token would really be redundant or not.
: I realise this might be a practical limitation of this approach as in some real-world APIs there are legitimate POST routes that don’t take a request body or there may be routes that need to take a content-type like form-data that won’t trigger a preflight.