Clean Way to Work With JWT —
Working with JWT is a headache specially when you’re starting out building a stateless backend system.
Note: This is not an introduction to JWT ( JSON Web Tokens) or any tutorial to implement JWT from scratch.
In JWT, the token is the most important piece of information to identify the user in the system. If user is able to tamper, see and modify the JWT by any means, then he/she’ll be able to perform identity theft with XSS / CSRF attacks when not secured properly.
Let’s try to approach this problem by whatever comes in mind.
What if we tried to save the token in local storage and send it in header on every request?
If a potential attacker has access to local storage, he can perform whatever he desires while the backend recognizes him to be the JWT Stored User.
And he hacker will have access forever, now what if user changes password what will you do?
Store it in database.
If you store the credentials in database and validate if the password has changed since the last token was issued, it’ll help you a little bit. But that’s not the point of JWT. The point of using Token Based Authentication like JWT is make sure the authentication system is maximum stateless as possible.
Let’s change the thought a little bit. What if the token expires after short time? And a new token is issued.
What ? A user logs in every(short)time?
No, let’s not do that way. It’s a terrible UX to login everytime. You can minimize UX such a terrible way just to make sure hacker doesn’t get access for long time.
Let’s use another token called refresh token which will stay with access token but have a greater expiry time. This works, now how will you make sure refresh token is used to refresh after access token is done (expired)?
Expose two endpoints
This works. But not for a long. A sensible hacker will request jwt forever and try to maximize his session as possible.
Keep in mind, our storage of JWT problem is not solved yet.
Covering the expiry part…
When you specify expiry time in jwt token, it won’t be valid token after the time has expired.
Now, the UX won’t be that bad and the token will keep on refreshing every time but how to make sure client / hacker doesn’t have reach to that token?
What kind of cookies? If you store JWT in plain cookies, that’s how 90% of XSS attacks escalate to massive impact.
Using HTTPOnly Cookies
HTTP Only cookies are such kind of cookies which can’t be accessed and read from the client but will be stored on the client and passed on every request, which means the cookie works sort of like session but in a completely stateless manner.
The above code issues a two token which will be expired after 20m and 7days while the cookies can’t be read from the client.
This protects us from maximum attacks.
Little Help to Developers
This is how we can write a middleware to make sure, the token is validated and try to refresh the token if there’s any.
Make sure, your CORS enables frontend to work with HTTPOnly Cookies by following…
Keep in mind, origin can’t be wildcard when credentials is true..
You can login in this way…