There is always a need for Authentication when building an application. And if you're a developer, you know how painful the authentication part can get. It takes a significant amount of effort to build this part if you're starting from scratch. Also, it is a little difficult to understand how it works at once. I still struggle every time I try to implement it.
Let's look at a way of implementing an access token and refresh token system using JWT.
Generally, during the creating of one token, we need to specify three things - The payload, a secret key, and the algorithm to create the token. The payload is the data we need in the token. There are a few general keys like 'sub', 'iat' (issued at), etc but it can be customized.
We need to specify the algorithm because there can be multiple of those, which can be used for the creation. The important thing is the secret key. Anyone can create a token with the same payload and algorithm. So to verify that it is created by our server, we need the key.
Now, let's see how the access token and refresh token works. So, once the user login we create a jwt as discussed above which works as an access token. It contains the user information in the payload. We send this to the front-end and store the access token there.
It can either be stored in localStorage or your store (redux, vuex or whatever). Now we send this token along with the requests to the backend, and for every secured route (the one which we need the user to be logged in) on our backend, we check this access token on our backend.
We check the expiry for that token on the frontend itself before sending the request to the backend. It can be set by us while creating. This part can be customized. This is generally intercepting your own request and checking. The access token is also added to the request in this step.
Now, for checking this access token on the backend, as mentioned before we decode it with the help of our secret key. Now if everything goes well, we allow that request. If it doesn't that means the token has been tampered with. We throw the user out in this case.
A refresh token is also created during the login, but we don't usually create a jwt for that. You can create it by any library or even use a simple uuid to create a unique token string. We store this along with the expiry of the refresh token in our database along with the user.
This refresh token is also sent to the frontend and usually store as a cookie, so it is by default sent to the backend with the requests. If the access token is expired (during the interception), we use this refresh token and validate with what is stored in our database.
We send the request to a refresh route created by us to check if it is a user's refresh token and not expired. If it is not expired we generate a new access token for that user as we did during the login and the process is the same again.
If it is expired, we log the user out.
So, most of the time we are using the access token to verify if the user is authenticated. But if the access token is expired, we use our refresh token to create a new access token.
There can be multiple approaches to this according to the need and comfort.
If you have any questions or suggestions, please leave a comment below or feel free to reach out.