Hey everyone, this is my first post so go easy on me :P
So I want this post to help anyone who wants to build an authentication system. I'm sharing a workflow, not the implementation, so that you can change the implementation in the way of your needs.
I'll add some scenarios throughout the post and will move on to server-side and lastly client-side. I'll assume that you already have a registration system.
User registered. Okay, then we need to send a jwt and a refresh token. So server creates it and sends them back to the user, user's browser saves tokens then our cute little user is free to roam around in our app. So what happened actually?
- Client registered
- Created a short-lived JWT and a refresh token for the specified user
- Save the refresh token in a DB, it can be a Key-Value DB like Redis.
- Send JWT back to client, and add the refresh token to client's Cookie Storage with HttpOnly and Secure flags.
You can set cookie in node like this:
response.setHeader('Set-Cookie', 'foo=bar; HttpOnly');
- Hit server's registration endpoint.
- Save JWT to localStorage.
As a note: Local storage is vulnerable to XSS attacks so becareful :)
Okay that wasn't that much. But a couple of questions can be arised with our little note. Here's the most specific one: Why did we save JWT to localStorage if it is vulnerable?
We have saved JWT to client's local storage because you might have noticed, our JWT is short-lived, say 30 minutes. This way we can add JWT to Authorization header of our API requests. (The bearer thingy)
This way when user hits our API, our server can validate the JWT and refresh token of the user.
User never gets bored in our app! He constantly refreshes the feed and wait for new things, but guess what our little user? 30 minutes have passed already! So your JWT is EXPIRED. Now what?
This time I'll explain it like a sequence diagram.
- User makes an API request with expired JWT.
- API request is received, check the JWT and refresh token. BOOM JWT is expired, send unauthorized response to client (401).
- Received unauthorized response from the previous API request.
- Hit refresh endpoint of the API.
- Received the expired JWT checked it and refresh token is assigned to current user. Now refresh the JWT and send it back to user.
- Received JWT, saved it to the localStorage again.
- Repeat the failed API request.
- Continue to operate.
In node's jsonwebtoken package, there's an option while verifying the jwt. It is ignoreExpiration. You can check if the token is modified.
So our user is sleepy, he wants to logout. But it's not that he got bored, he just wants to sleep :). He clicked the logout button. What happens now?
- Clear the localStorage or just remove the jwt.
- Make an API logout request.
- Received logout request. Delete refresh token from the DB (like redis :P)
- Set refresh token cookie's expiration date to any date in past.
Poof our user is logged out.
Such a long post for the first time eh? I might add more information if posts can be edited :P.
Important note: Mobile authentication should be different than this. I will share a post about it in future.
See you in another post!