278

Quick note: this is not a duplicate of CSRF protection with custom headers (and without validating token) despite some overlap. That post discusses how to perform CSRF protection on Rest endpoints without discussing if it is actually necessary. Indeed, many CSRF/Rest questions I've read on this site talk about securing the endpoints via CSRF tokens without actually discussing whether or not it is necessary. Hence this question.

Is CSRF Protection necessary for Rest API endpoints?

I've seen lots of discussion about securing REST endpoints against CSRF attacks, but having given the topic lots of thought, I'm very certain that CSRF tokens on a REST endpoint grant zero additional protection. As such, enabling CSRF protection on a REST endpoint just introduces some useless code to your application, and I think it should be skipped. I may be missing something though, hence this question. I think it will help to keep in mind why CSRF protection is necessary in the first place, and the attack vectors it protects against:

Why CSRF?

It really boils down to the browsers ability to automatically present login credentials for any request by sending along cookies. If a session id is stored in a cookie the browser will automatically send it along with all requests that go back to the original website. This means that an attacker doesn't actually have to know authentication details to take an action as the victim user. Rather, the attacker just has to trick the victims browser into making a request, and the credentials to authenticate the request will ride along for free.

Enter a REST API

Rest API endpoints have a very important difference from other requests: they are specifically stateless, and should never accept/use data from either a cookie or session. As a result, a REST API that sticks to the standard is automatically immune to such an attack. Even if a cookie was sent up by the browser, any credentials associated with the cookie would be completely ignored. Authentication of calls to a REST API are done in a completely different fashion. The most common solution is to have some sort of authentication key (an OAuth Token or the like) which is sent along in the header somewhere or possibly in the request body itself.

Since authentication is application-specific, and since the browser itself doesn't know what the authentication token is, there is no way for a browser to automatically provide authentication credentials even if it is somehow tricked into visiting the API endpoint. As a result, a cookie-less REST endpoint is completely immune from CSRF attacks.

Or am I missing something?

8
  • Some REST API are limiting calls per ip, that may be an edge case where it could make sense to implement a csrf protection.
    – Xavier59
    Commented Aug 3, 2017 at 18:51
  • 2
    Thanks for the input @Xavier59. Do you mind clarifying: why would rate limiting necessitate CSRF protection? Commented Aug 3, 2017 at 19:01
  • So I'm not confident that this is necessarily applicable to your case, but let's say you use google as an oauth provider. Your user logs in to some malicious site which also uses google as an oauth provider. The malicious site could use the user's token (ish, depending on client settings and such) for your site. See here for more: spring.io/blog/2011/11/30/cross-site-request-forgery-and-oauth2
    – Jesse K
    Commented Aug 3, 2017 at 19:02
  • @ConorMancone If site A has a REST API limiting call per ip to 1/second, an attacker could trick Bob to go on attacker site B which send tens of request per second. It could result in getting Bob's ip banned from this REST API or preventing him to use the REST API correctly. I agree that's a bit farfetched but not totally impossible.
    – Xavier59
    Commented Aug 3, 2017 at 19:48
  • 1
    @Xavier59 That is somewhat the equivalent of trying to DDoS a website by getting an img tag with the website as its source attribute on a high-traffic website. It isn't necessarily far-fetched. That being said, I don't see why CSRF tokens would do anything to mitigate such an attack. Commented Aug 3, 2017 at 20:11

7 Answers 7

305

I wasn't originally aiming for a self-answer, but after more reading I've come up with what I believe to be a comprehensive answer that also explains why some might still be interested in CSRF protection on REST endpoints.

No cookies = No CSRF

It really is that simple. Browsers send cookies along with all requests. CSRF attacks depend upon this behavior. If you do not use cookies, and don't rely on cookies for authentication, then there is absolutely no room for CSRF attacks, and no reason to put in CSRF protection. If you have cookies, especially if you use them for authentication, then you need CSRF protection. If all you want to know is "Do I need CSRF protection for my API endpoint?" you can stop right here and leave with your answer. Otherwise, the devil is in the details.

h/t to paj28: While cookies are the primary attack vector for CSRF attacks, you are also vulnerable if you use HTTP/Basic authentication. More generally, if the browser is able automatically pass along login credentials for your app, then CSRF matters. In my experience cookies are the most common technology being exploited to make CSRF happen, but there are some other authentication methods that are used which can result in the same vulnerability.

REST = Stateless

If you ask someone "what is REST" you will get variety of answers that discuss a variety of different properties. You can see as much because someone asked that question on stack overflow: https://stackoverflow.com/questions/671118/what-exactly-is-restful-programming

One property of REST that I have always relied upon is that it is stateless. The application itself has state of course. If you can't store data in a database somewhere, your application is going to be pretty limited. In this case though, stateless has a very specific and important meaning: REST applications don't track state for the client-side application. If you are using sessions, then you are (almost certainly) keeping track of client-side state, and you are not a REST-full application. So an application that uses sessions (especially for logins) that are tracked via cookies is not a REST-full application (IMO), and is certainly vulnerable to CSRF attacks, even if it otherwise looks like a REST application.

I think it is worth a quick note that one reason that client-side statelessness is important for REST applications is that the ability of intermediaries to cache responses is also a desirable part of the REST paradigm. As long as the application is tracking client-side state, caching is not possible.

Rest ≠ Cookieless

For these reasons, I initially assumed that a fully-compliant REST application would never need sessions, never need cookies, and therefore never need CSRF security. However, there is at least one use-case that may prefer cookies anyway: persistent logins.

Consider a typical client-side (in this case browser, not mobile) web application. You get started by logging in, which uses a REST API to validate user credentials and in return is given a token to authorize future requests. For single page applications, you can just keep that token in memory, but doing so will effectively log the user out if they close the page. As a result, it would be good to persist the state somewhere that can last longer than a single browser session. Local storage is an option, but is also vulnerable to XSS attacks: a successful XSS attack can result in the attacker grabbing your login tokens and sending them off to the attacker to be used at their discretion.

For this reason, I have seen some suggest using cookies to store login tokens. With a cookie you can set the http-only flag, which prevents the application from reading the cookie after it is set. As a result, in the event of an XSS attack, the attacker can still make calls on your behalf, but they can't walk away with the authorization token all together. This use of cookies doesn't directly violate the statelessness requirement of REST because the server still isn't tracking client-side state. It is just looking for authentication credentials in a cookie, rather than the header.

I mention this because it is potentially a legitimate reason to use cookies with a REST API, although it is obviously up to a given application to balance the various security and usability concerns. I would personally try to avoid using cookies with REST APIs, but there may very well be reasons to use them anyway. Either way, the overall answer is simple: if you are using cookies (or other authentication methods that the browser can do automatically) then you need CSRF protection. If you aren't using cookies then you don't.

17
  • 14
    You're pretty much spot on. HTTP basic authentication can be vulnerable to CSRF as can IP-based auth and others. Conversely, Cookies can be safe if it's only ever a bespoke client that consumes the service, not a browser. That probably doesn't affect your decisions, but is worth bearing in mind. I've found people trying to define what is "proper REST" to be one of the least constructive discussions in IT. In practical terms, most services need authentication, and sessions are a reasonable way to do it.
    – paj28
    Commented Aug 7, 2017 at 17:48
  • Thanks @paj28. HTTP basic authentication is a great point to mention. It's a lot less common, I think (which is why I forgot to mention it), but it is good to mention the exceptions when you are trying to come up with a comprehensive answer. Commented Aug 7, 2017 at 17:59
  • 3
    One small clarification: "No cookies = No CSRF" - I thought so too, but with Kerberos/NTLM native browser support, (SPNEGO) a kerberos token is being sent out to a set of whitelisted domains. These cases should also have CSRF protection as it's essentially the same as a cookie in the way that "something that is automatically sending something out on requests" so I think if you submit a form with target being a kerberized API endpoint, while you are in the internal network, there is a CSRF risk here too, no?
    – Eran Medan
    Commented Jul 16, 2019 at 22:28
  • 2
    Another one about "No cookies = No CSRF" - if you store session token in the URL (bad idea, but happens), then it's as easy to trick user into form submission as with session token in cookies. This would require getting to know token in advance (browser history / proxy logs / server logs) which is an obstacle, but is doable under certain circumstances. Very specific case, but I thought it's worth to mention.
    – adamczi
    Commented Mar 16, 2020 at 9:42
  • 1
    I'd like to expand a bit on something @paj28 alluded to. CSRF can be a problem when the server in question is relying on the client's network location for security. Either via an actual network separation (server only available on VPN, eg) or by explicitly looking at the source IP as part of its logic. In this case the attacker isn't taking advantage of secrets stored in the browser, but of the browser's "location". Chrome has some partial mitigations here (wicg.github.io/private-network-access) but other browsers don't. Commented May 17, 2022 at 0:07
16

Whether or not CSRF protection is needed is based on 2 factors: -

Is the request doing a state changing action (not the same as REST API Statelessness) - State changing actions are any action that will change the state of the application.. for example delete something, add something, update something. These are actions using which the application will change the backed state of the user. All Post requests and a few Get requests will come under this category. REST APIs can have state changing actions.

Is the authentication provided by browser (not limited to cookies) - CSRF happens because authentication information is included in the request by browser irrespective of whether the request was started by the user, or some other open tab. So any kind of authentication in which browser can self include information needs CSRF protection. That includes both cookie based sessions and basic authentication.

For all requests that fall in above 2 categories CSRF protection is needed.

13

"there is no way for a browser to automatically provide authentication credentials even if it is somehow tricked into visiting the API endpoint"

Just be careful on private networks using integrated windows/kerberos authentication. In this scenario the brower will automatcially provide credentials (kerberos or NTLM token) if configured to do so.

So - I believe in this case CSRF is required.

1
  • 2
    Yep. owasp.org/index.php/Top_10_2007-Cross_Site_Request_Forgery "Authorizes requests based only on credentials that are automatically submitted such as the session cookie if currently logged into the application, or “Remember me” functionality if not logged into the application, or a Kerberos token if part of an Intranet participating in integrated logon with Active Directory is at risk."
    – Eran Medan
    Commented Jul 16, 2019 at 22:39
6

One thing I would add to the other answers is that CSRF protection is necessary only in the domain and path of the cookie in question. Or put another way:

Authorization != Authentication
Cookies == Authentication
Token == Authorization

This is relevant to the implementation of persistent logins (your 3rd point). If you affix your cookies to login.example.com, which hosts your login UI and your /authorize endpoint, then you can run an implicit OAuth flow every few minutes without requiring a new login (e.g. no password dialog). The client can go ahead and send the access token thus acquired to api.example.com without CSRF, as no cookies will be sent to that host.

So, you can still safely avoid dealing with CSRF on your REST APIs. But your login / authentication server better be bullet-proof (and CSRF protected).

0
4

Rest API endpoints have a very important difference from other requests: they are specifically stateless, and should never accept/use data from either a cookie or session.

If that is how you define "REST API", then no CSRF is possible. CSRF, also called "session riding" [citation], obviously won't work if there is no session to "ride."

4
  • 1
    If you disagree with part of my statement I would be happy to hear it. IMO, statelessness is a central goal of REST APIs. Sessions definitely make an API stateful. Cookies... technically I suppose you could use cookies and not be storing state server side, depending on how you use them. Commented Aug 3, 2017 at 20:44
  • 1
    Well I'd rather answer the question than quibble over terminology. But the S in HATEOS and the S in REST both stand for state. As long as client state isn't held on the server I don't think you've "violated" the spirit of the REST approach.
    – John Wu
    Commented Aug 7, 2017 at 16:13
  • I absolutely agree with you. It wasn't my desire to quibble over terminology. Part of the problem is that I wasn't clear enough in my original question: I was specifically talking about client state, not application state. Commented Aug 7, 2017 at 17:40
  • Yes State Transfer, that's the important point. The state isn't stored on the server side. The client tells the server about his state. And CSRF makes only sense if the api is accessible through regular web browsers. Some http methods like DELETE, PUT/PATCH are not even supported by todays browsers which makes the api only accessible to stand-alone http clients.
    – Sebi2020
    Commented Sep 13, 2018 at 1:54
3

Answer : If you store the token in the localStorage and append it to your requests with JS, it would automatically guarantee CSRF protection (by the nature of the attack)

Addendum : As of whether it is more safe to use http-only cookies rather than localStorage (making it seem like this way of having CSRF protection would create a problem in case of XSS) : it is actually not. It would just make it a tiny bit harder for the attacker who is in control of JS on your site through an exploited XSS. @bobince have explained that with better words : Does setting httponly prevent stealing a session using XSS?

XSS is application level vulnerability, but its effects can be mitigated by limiting the power of the token through the usage of claims (restrict to minimum necessary)

6
  • 2
    Welcome. As a Q&A site, we are different from a discussion site. Answers need to stand alone as an answer to the question and not a comment on another answer.
    – schroeder
    Commented Feb 7, 2020 at 10:01
  • @schroeder Thanks. Long time lurker first time poster, originally I wanted to comment but that required minimum reputation. However that comment lead to my original answer to the OP question in my last sentence : "should i use csrf protection" => No if the token is stored and appended to the header by JS
    – Raywell
    Commented Feb 7, 2020 at 10:08
  • All I can say is: keep contributing to the site to gain enough rep to unlock the ability to comment. You've made the first step in coming out of the "lurk". Keep going :)
    – schroeder
    Commented Feb 7, 2020 at 10:09
  • I'd recommend that you remove the comment to the other answer and make sure this answer directly addresses the question.
    – schroeder
    Commented Feb 7, 2020 at 10:12
  • I can, but I think it's quite important because it makes all the difference (reasoning leading to the answer). I will clarify the conclusion
    – Raywell
    Commented Feb 7, 2020 at 10:14
2

There's a small specific caveat to existing answers that I'd like to add. While Conor is right that cookies are the only form of locally stored authentication data sent along all requests, they're not the only form of locally stored authentication data used by websites. What this means is, if a site decides to keep their JWTs/Session tokens in something like LocalStorage or SessionStorage, these can still sometimes be automatically pulled out via javascript and then used without user interaction. That means it is sometimes still possible to perform CSRF attacks "once removed" by redirecting a user to a domain-matching frontend URI that then sends the creds along. This can be accomplished in a more direct way if you have reflected XSS, but there are cases where this is unnecessary and such pages+scripts already exist.

In these cases, the problem isn't the lack of CSRF tokens on the REST API; it's the lack of tokens on the endpoints of whatever frontend is interacting with it.

2
  • Wow, that is genial! So trivial, if a JS could be somehow injected into the target site, any session can be stolen.
    – peterh
    Commented Aug 13, 2020 at 6:31
  • @peterh-ReinstateMonica Cute, but as I said in the post that's not what I meant. It's not uncommon you have a frontend sitting in front of the rest API with some endpoints that already perform mutative actions upon load, without requiring you to inject code into them. Commented Aug 13, 2020 at 7:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .