Home > Enterprise >  Best way to check jwt token expire status if stored in localstorage
Best way to check jwt token expire status if stored in localstorage

Time:09-28

I want to check if the token is expired on client side.

My token is stored in localstorage.

Now what I do is: make a call to the server to check if it is valid but I only do it when the path is: https:exp.com/

code:

  useEffect(() => {
    verifyToken(auth.token).then((res) => {
      if (res.status !== 'success' && res.message === 'Token expired') {
        signoutClient(() => {
          router.push('/auth/login');
        });
      }
    });
  }, [auth.token, router]);

Now the problem here is what if the user goes directly to another url exp : https:exp.com/helloworld

I was thinking to use sockets but I don't know if it could work.

Idea is: client stays in listen, whenever token expires server emits a message.

Any idea on how can I do it?

CodePudding user response:

There are different techniques.

Note that handling time on two different machines (expiration in this case) may lead to issues due to time jitter or clock misalignment, so it is not so straightforward

Passive expiration

My favorite pattern is to have a dedicated server error.

Your server should respond with a particular error when the token is expired (to be distinguished from the 401 Unauthorized due to role access). You then add an HTTP middleware to your client that:

  • detects this error response
  • deletes local token and navigates to /auth/login

Or if you have a renew token:

  • detects this error response
  • attempts to renew the JWT
  • repeats the original request on success OR navigates to auth page on failure.

This is a passive system that allows you to treat the JWT as an obscure string and does not have time-related issues.

Return a separate field

If, for security reasons, you want to hide sensible information when the session expires even when the user is not interacting with the UI (like Banking sites do) you need to know when the token will expire. A common technique is to return expiration time together with the token (within the authentication response).

{
   "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.JFDV4mOKKh0sMfkBKvsbvm8iWjHEGBXtPvC49ob3qiI",
   "expiresAt": 1234567890
}

Or even better

{
   "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.JFDV4mOKKh0sMfkBKvsbvm8iWjHEGBXtPvC49ob3qiI",
   "expiresIn": 600
}

The first one returns you the UNIX time of token expiration relative to server time. This is subject to time jitter or clock misalignment (this may lead to errors). The second one is better as it lets the UI know within how many seconds (since the Response was received) the token will expire, this can be then used to calculate the UNIX time according to the local clock.

It is common to remove a small time step from expiresAt and expiresIn to avoid clock jitter and clock drift issues.

Parse the JWT

If you have no other solution, you can always parse the JWT:

const JWT = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEyMzQ1Njc4OTAsIm5hbWUiOiJKb2huIERvZSIsImlhdCI6MTUxNjIzOTAyMn0.1c_yQjnMZfKUb4UTDE_WvbC71f8xxtyMsdqKKkI1hF8`;

const jwtPayload = JSON.parse(window.atob(JWT.split('.')[1]))
console.log(jwtPayload.exp);

CodePudding user response:

You can use a lib(like jwt_decode) to decode your JWT token, where it's most likely contains an expiration timestamp that you can check(compare it with the current timestamp for this moment) and if it exceeded(expired) just delete it from local storage and redirect user to login page.

But you also have to consider add a catch block for functions which calls your API to check for any 401 response status code to also do the same (in case the token was valid then while the user is moving around its expiry date ends)

  • Related