CSRF protection for REST APIs

I want to implement CSRF protection for REST apis authenticated using Token authentication. Usually REST apis don’t need CSRF protection, unless we store the token in the cookie for remembering the user after browser restart. (https://security.stackexchange.com/questions/166724/should-i-use-csrf-protection-on-rest-api-endpoin…)

So I enforced CSRF and returned it as a cookie. Javascript on frontend would read the cookie, get the csrftoken and pass it under X-CSRFToken header for validating all the subsequent requests. Now what concerns me is that HTTPONLY flag for this cookie has to be set False, for JS to read it, but then I have made it vulnerable to cross scripting attacks. If hacker gets the csrf token, he can easily forge a cross site request.

From the django page Settings | Django documentation | Django

“This makes it less trivial for an attacker to escalate a cross-site scripting vulnerability into full hijacking of a user’s session. There aren’t many good reasons for turning this off. Your code shouldn’t read session cookies from JavaScript.”

I am thinking, instead of javascript reading the csrf token from the cookie, I can create a separate GET api which will send CSRF cookie in header and csrf token in body. the csrf token will the stored in-memory on frontend. And this api can be called to get a new set of cookie and token, in cases of browser restart or cookie expiry. This get api will be session indendependent. It shall send unique values everytime. It wont require any session cookies. It will be the first request the website will make for any anonymous user and it will set CSRF cookie on the browser. The cookie will be marked same site and httpy only as true. So it can also prevent login CSRF. Am I missing any loopholes here?

How are you storing the token on the client? If it’s not being stored and the client must authenticate each time the app opens, and the token is stored in memory, then the requirement for CSRF isn’t as strong. That’s because the the act of getting the token would be signaling to the server that the user is valid and can make requests. If you were to also supply the CSRF token as you suggested, it’s still susceptible to the same leaking vectors as the authentication token. You gain nothing, but have to implement more code.

If you are storing the authentication token in the cookies:

Is it possible for you to supply the CSRF cookie back to the server in the requests to the API? (if you’re using fetch, there’s the credentials param) Then you could keep it as a http only cookie.

1 Like

If I return it in the cookie, I have to set HTTP only flag false, and JS would read it and pass it in under X-CSRFToken header, but that would make it susceptible to XSS attack.

And as you said storing it in memory does not do any good.
So what is the standard way of ensuring CSRF protection for REST api based website?

Sorry, I meant how are you storing the authentication token, not CSRF token.

How does the client make requests to the API server? Are you using fetch, axios or something else entirely?