JWT, or JSON Web Tokens, has become the standard for secure authentication in modern web development.
But we usually generate the JWT when the user logs in. And the question is: how much time must the JWT be valid until the next user log in?
But what if your users don’t have to constantly log in to access their data? That’s where renewing JWTs comes in.
In this post, I will explore how to renew JWTs without requiring the user to log in again. Making authentication quick and effortless for both the user and the developer.
The Problem
Setting the expiration time when creating a JWT may be a tricky question.
If it’s too long, it has more chances to be hacked.
If it’s too short, it interrupts user’s navigation.
If I set the expiration time to the JWT to one hour, I don’t want to ask the user to log in again after one hour.
If I don’t set an expiration time to the JWT, it’s worst. If intercepted, the hacker has all the time to figure out the secret key.
So, the goal is to decrease the expiration time to less than an hour.
The Solution
A solution may be to renew the JWT at each request.
Every time the frontend makes a request, the backend returns a new JWT with an expiration time of 10 minutes.
But if I have an inactivity of more than 10 minutes, the user will have to log in again.
And generating JWT every time isn’t the best practice. What if the frontend makes two requests at the same time? Which JWT must I save?
Here is a solution I’ve implemented in a recent project.
When the user logs in, the backend returns a JWT with an expiration time very short, let’s say 10 minutes.
With this first JWT, the backend also returns another JWT, I will name it renew-JWT. The frontend can’t use the renew-JWT to request the backend.
The renew-JWT has only one purpose.
I create a new endpoint in the backend. If the login endpoint is /auth, I create a new one as /auth/renew.
This new endpoint accepts the renew-JWT as the only parameter.
The renew-JWT has an expiration time higher, but it also has another claim named “not before”. This second claim says I cannot use the token before a date.
And I set this “not before” date to the expiration time of the JWT.
The Workflow
So, here is the workflow:
- The frontend requests /auth;
- The backend returns the JWT with an expiration time of 10 minutes. In the same body, it also returns a renew-JWT with a “not before” of 9 minutes and an expiration time of one hour;
- The frontend uses the JWT to request the backend in the Authorization Bearer header;
- After 10 minutes, the JWT expires and the frontend can’t use it anymore;
- The backend returns now a 403 HTTP code when using the JWT;
- The frontend uses now the renew-JWT with the /auth/renew endpoint;
- This will return a new valid JWT and a new valid renew-JWT;
- The new JWT has an expiration time of 10 minutes. And the new renew-JWT has the “not before” claim to 9 minutes and an expiration time of one hour;
- The user can have an inactivity of one hour without asking him to log in again.

The Advantages and Disadvantages
The Advantages
- The JWT has the less expiration time possible;
- I can’t use the renew-JWT to request protected information
The Disadvantages
- The renew-JWT has a higher expiration time, a lot of time to try to hack this JWT;
- I can use the renew-JWT many times to generate many valid JWTs.
Conclusion
I’ve been using this solution for about two years. the main advantage is to have a lower expiration time in the JWT and don’t ask the user to log in frequently. The problem wasn’t moved from the JWT to the renew-JWT, as the renew-JWT has not the same usage. I can’t request protected data with the renew-JWT.
It may not be the best solution, but in my opinion, it’s a good practice. If you have an idea to optimize this solution, let me know in the comments.
If you want to learn more about good quality code, make sure to follow me on Youtube.



Leave a reply to 5 Essential Tips for Securing Your Spring Application – The Dev World – Sergio Lema Cancel reply