49

I've been reading about JWT, and from what I understand, it's a token that the server sends after a user logs in. The user will have to send that token with all future HTTP requests. This creates a stateless way for the server to verify a user's request.

Now what I don't understand is that if the JWT is sent in the header and marked as HTTP only, why is a CSRF token also needed for prevention of CSRF attacks? My understanding is that both JWT and CSRF tokens are tied to a user, and that a JWT would serve both purposes.

I understand that CSRF tokens are used so HTTP requests from other sites won't be accepted. How does a JWT not accomplish that? What separates a CSRF token from a JWT token, and allows it to accomplish that difference?

I've been reading articles on JWT's and CSRF tokens as well as the double submit method, but there is just something I can't seem to understand or I'm missing.

Community
  • 1
  • 1
Caciano
  • 747
  • 1
  • 6
  • 13

2 Answers2

47

An authentication system based on tokens (JWT or random) stored in cookies is vulnerable to CSRF attacks, because cookies are sent automatically to server in each request and an attacker could build a harmful url link to your site.

https://yoursite.com/delete?something=1

To protect your site it is needed to use a CSRF token that your application must send in the following request (not in a cookie).

Alternatively you could store the JWT in localStorage and send it in a Authorization header, then your site is protected against CSRF, but it could be vulnerable to XSS attacks. Take in account always the security considerations of the technical solution you choose

Update ¿why storing JWT in localstorage could be vulnerable to XSS attacks?

See this comparison between storing tokens in localstorage and http-only cookies https://academind.com/tutorials/localstorage-vs-cookies-xss

An attacker could inject javascript code to read the token from the localstorage and send it to his own server. However, this type of attack is not possible with an http-only cookie because it is not accessible from javascript

pedrofb
  • 37,271
  • 5
  • 94
  • 142
  • I dont get it, if you store the csrf token not in a cookie, then lets say you store it in session storage, couldnt an attacker simply read that and send it? Also, in this article https://en.wikipedia.org/wiki/Cross-site_request_forgery#Cookie-to-Header_Token they store the csrf in a cookie – Caciano Aug 29 '17 at 20:02
  • 1) an attacker can not read data of a page in a different domain. This is called `same-origin` policy. 2) In your link the cookie is set but it is read with javascript and sent in a header( it is not httponly), it is not automatically sent by browser, that is the key point of a CSRF attack – pedrofb Aug 29 '17 at 20:40
  • 5
    Why storing JWT in localStorage could be vulnerable to XSS attacks? Could you explain? @pedrofb – Khanh Le Sep 27 '18 at 04:09
  • 1
    @LittleZero, you can find here some localStorage vulnerabilities https://www.owasp.org/index.php/HTML5_Security_Cheat_Sheet#Local_Storage and here XSS explained http://michael-coates.blogspot.com/2010/07/html5-local-storage-and-xss.html – pedrofb Sep 27 '18 at 06:53
  • 2
    The article you have provided on "why storing JWT in localstorage could be vulnerable to XSS attacks", IMO, takes the opposite view. It says that even if you store token in cookies, the attacker can do this `onerror="fetch("https://localhost:3000/buy-product?prodid=abc", { credentials: "include", method: "POST" })'` And they don't care about your token. As for "..and send it to his own server" - and what would they do after they get the token on their server? Go to your site on some state-modifying endpoints with it. Which is, well, just an extra step, to the approach above. – Sviatozar Petrenko Jun 02 '22 at 20:13
  • Just make API fetch with `credentials: 'omit'` to not send all cookies automatically and just send your jwt in `Authorization: Bearer ${token}`. And you are done with the highest security possible lol !!! – Thomas Aumaitre Sep 07 '22 at 17:19
  • "Alternatively you could store the JWT in localStorage and send it in a Authorization header, then your site is protected against CSRF, but it could be vulnerable to XSS attacks. " Same also applies to CSFR token? – Denis Jan 07 '23 at 21:04
4

All your questions are relative to the fact that a CSRF token in NEVER included in a cookie and that a JWT token MAY be sent in a cookie.

A JWT token can be sent:

1- in a cookie

2- in another type of header

3- outside the headers, in some POST attribute

4- outside the headers, in some GET parameter (not very common)

But for stateless authentication, you MUST use cookie (case 1).

So, for stateless authentication, you are prone to CSRF, with your JWT token. This is why you need to add some CSRF mitigation mechanism, based on some more information not included in a cookie, or not only included in a cookie.

All of this would not apply if you were accepting to implement a stateful authentication.

Alexandre Fenyo
  • 4,526
  • 1
  • 17
  • 24
  • yes, i am going for a stateless authentication, I dont get it, if you store the csrf token not in a cookie, then lets say you store it in session storage, couldnt an attacker simply read that and send it? Also, in this article https://en.wikipedia.org/wiki/Cross-site_request_forgery#Cookie-to-Header_Token they store the csrf in a cookie – Caciano Aug 29 '17 at 20:05
  • In this article, they do exactly what I said: they use a CSRF mitigation mechanism based on some information **not ONLY included in a cookie**. Read again the article: the JS *copies it into a custom HTTP header* (X-Csrf-Token). Concerning the session store, if you know how an attacker can *simply* read it, then you have a big problem: your application is affected by a XSS flaw. If this is the case, you should mitigate this flaw, but this is another story. – Alexandre Fenyo Aug 29 '17 at 20:40
  • Am I right asserting, that once you have an XSS vulnerability, token based CSRF protection is quite a low concern, as a properly designed XSS attack can easily obtain a proper CSRF token for their malicious request, and it would not provide a great protection anyway? – Bence Szalai Aug 27 '20 at 17:29