local-storagecsrfjwtauth0

CSRF protection with JSON Web Tokens


I read that when using JWT, there is no need to protect against CSRF attacks, for instance: "since you are not relying on cookies, you don't need to protect against cross site requests".

However, something I do not understand: if I store the token in localStorage (as I was advised on a tutorial of the same website), what prevents an attacker to forge a malicious request by reading my localStorage instead of my cookies?

Since it was generated on the server side, I don't get how I could use a token for a client request without it being stored somewhere on the client.


Solution

  • Strictly speaking, yes, anything stored in local/session storage (which I'll call HTML5 Storage) could be stolen in a cross-site scripting (XSS) attack. See this article.

    There are a lot of moving parts to consider, however.

    First, there are subtle differences in how HTML5 Storage and cookies are scoped with respect to JavaScript access.

    HTML5 Storage is:

    Cookies are more loosey-goosey:

    Second, since cookies are marked with a domain, when a request is made to a server, the browser will send all-and-only cookies with a matching domain, regardless of the domain of the page that originated the request.

    The last part is how a CSRF attack is accomplished (the same-origin policy only helps so much). The OWASP page on CSRF is a good resource for learning how these kinds of attacks work.

    The reason storing an authentication token in local storage and manually adding it to each request protects against CSRF is that key word: manual. Since the browser is not automatically sending that auth token, if I visit evil.example and it manages to send a POST http://example.com/delete-my-account, it will not be able to send my authn token, so the request is ignored.

    With the above in mind, whether to use a cookie or HTML5 Storage becomes a series of tradeoffs:

    Storing the authen token in HTML5 Storage means:

    On the other hand, if you store the authn token in a cookie marked httpOnly and secure, then:

    Which option is better depends on your needs.