I'm going to avoid jargon here as much as I can. So let me explain things in simple words.
What is JWT?
It's a token, or let's say it's a string that if you, the user of the app, own it, then you can access or update certain things on the server.
For example, if you want to update your profile picture, you should have the token that allows your account to update that profile picture.
Where does the user get this token from?
The server generates it for the user.
When does the server generate it?
When the user proves to the server that he or she can get one. This typically happens when the user logs in to the app.
So when the user fills in the username/password and presses log in, the server checks that they are correct, and if so, the server generates the token and sends it in the response of that log-in request.
What should the user do with the token?
The user should embed it with every request sent to the server. (Or at least with the requests that require authorization.)
How to embed it?
Typically, you would include it in the header of the request, specifically the Authorization
field.
If I have to include this token with every request, where should I store it?
You can use localStorage to store it, but that would open your app to XSS attacks. A better choice is cookies.
If I don't store it, should the user log in every time the page is reloaded?
Yep!
How can the server know that the included token can access a specific user's resources?
When the server generates the token, it includes the user's email, username, etc (anything it can identify the user with). So, for example, if the token contains your email address, then you can access only stuff related to the user with your email address.
So can the token hold data?
Yes it can, inside the payload section.
If someone stole my token, can they access my stuff?
Yes they can!
How can the server be sure that the user's token wasn't modified before it's sent?
When the server generates the token, it digitally signs it with a secret key.
I can dive further into what a digital signature is and how it's generated, but let's keep things simple here and just keep in mind that if you have a token and you modified it, the server won't give you access to anything because the token has been changed.
If I tried to use this token after 10 years, would it still work?
Yes, it will be valid forever unless the server specifies an expiration time when generating it.
That's it!
If you have any questions, ask them in the comments.
For more tips and tutorials like this, follow me on Twitter @tahazsh or subscribe to my blog's RSS feed.
Top comments (6)
Don't do it or it can be stolen by Javascript.
Updated the post. Thanks for pointing this out.
Thanks for the update, but you can improve it a little more, by telling to set the
cookies with the httpOnly flag set, otherwise we are back to the same issue of Javascript be able to steal it.
I would like to add that you probably need JWT only in one particular case: when the server or service that authenticates you (i.e. that verifies your identity, where you put your username/password) is DIFFERENT from the server that has to authorize you to take certain actions (e.g. publish a new post).
Typically it's OAuth scenarios, where the user uses the credentials of one system (say an enterprise Active Directory) to perform actions on a second system (a custom app hosted on a different server and domain), where you may want to use JWTs.
In most small/medium apps the server that logs you in is the same that will publish your post (think a standard Laravel app), and in this case the classic ID cookie is the best choice. Simplest and safest.
I would suggest that setting an expiration date less than 10 years in the future is probably a best practice.
I would say that you should always set one, that expires in some minutes, and use refresh tokens to extend the login session for some more time ;)