Which would be the best choice?
I have read that JWT protects the site from CSRF. However, I can't imagine how that would work assuming I save the JWT token in cookie storage.
How would it then protect from CSRF?
I saw some usage samples like the following:
curl -v -X POST -H "Authorization: Basic VE01enNFem9FZG9NRERjVEJjbXRBcWJGdTBFYTpYUU9URExINlBBOHJvUHJfSktrTHhUSTNseGNh"
How can I implement that when I make a request to server from the browser? I also saw that some implement the token in the URL:
If I would make a request via AJAX then I could set an header like
jwt: [token] and then I could read the token from header.
[EDIT] This answer is the accepted one, however the response from João Angelo is way more detailed and should be considered. One remark though and because the security pratices evolved since Nov. 2016, the Option 2 should be implemented in favour of the Option 1.
Look at this web site: https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
If you want to store them, you should use the localStorage or sessionStorage if available or cookies. You should also use the Authorization header, but instead of Basic scheme, use the Bearer one:
curl -v -X POST -H "Authorization: Bearer YOUR_JWT_HERE"
With JS, you could use the following code:
Choosing the storage is more about trade-offs than trying to find a definitive best choice. Let's go through a few options:
Authorizationheader with a
example.comcannot be read by
localStorage.setItem('token', 'asY-x34SfYPk'); // write console.log(localStorage.getItem('token')); // read
You don't need to do anything client-side as the browser will automatically take care of things for you.
Authorizationheader with a
You leverage the browser
document.cookie API to store and then retrieve the token when performing requests. This API is not as fine-grained as the Web storage (you get all the cookies) so you need extra work to parse the information you need.
document.cookie = "token=asY-x34SfYPk"; // write console.log(document.cookie); // read
This may seem a weird option, but it does has the nice benefit that you can have storage available to a top-level domain and all sub-domains which is something Web storage won't give you. However, it's more complex to implement.
My recommendation for most common scenarios would be to go with Option 1, mostly because:
Also note that the cookie based options are also quite different, for Option 3 cookies are used purely as a storage mechanism so it's almost as if it was an implementation detail of the client-side. However, Option 2 means a more traditional way of dealing with authentication; for a further read on this cookies vs token thing you may find this article interesting: Cookies vs Tokens: The Definitive Guide.
Finally, none of the options mention it, but use of HTTPS is mandatory of course, which would mean cookies should be created appropriately to take that in consideration.
This blog post has excellent side by side comparison of browser storage vs. cookies and tackles every potential attack in each case. https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/
The shorter answer / spoiler: cookies and add xsrf token in the jwt. Detailed explanation in the blog post.
You should NEVER, EVER store a JWT outside of memory.
If you want to persist a JWT for the duration of a long session (say 1 hour when a token has an expiry of only 15 mins), silently log the users again in the background whenever the token is about to be expired.
If you want to persist a JWT across sessions, you should use a refresh token. Which, BTW, is most of the time used for above purpose as well. You should store it in an HttpOnly cookie (well, more precisely, a sever sets is via Set-Cookie header, the front end calls the /refresh_token API endpoint.)
A refresh token, BTW, is the least of the evils; to complement it, you should ensure you are following best practices to mitigate XSS.
localStorage, sessionStorage, and cookies all have their vulnerabilities.
This is the best guide i have ever read on JWTs: https://blog.hasura.io/best-practices-of-using-jwt-with-graphql/
©2020 All rights reserved.