Check If Token Expired Using This Jwt Library

Check if token expired using this JWT library

This is the answer:

if (Date.now() >= exp * 1000) {
return false;
}

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

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);

How to check if a JWT Token has expired without throw exceptions?

If you use a different JWT library, you can do it easily enough. The auth0 JWT library has methods to parse and, optionally, verify the token:

import com.auth0.jwt.JWT;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;


DecodedJWT jwt = JWT.decode(token);
if( jwt.getExpiresAt().before(new Date())) {
System.out.println("token is expired");
}

jwt.verify() returns jwt expired when the expiration is 24h

So since the question is, how does jwt check the expiration date, it depends on basically on some properties that may be implemented according to the JWT RFC

One would be exp. In case a token expires before the current datetime, then the JWT cannot be processed

The "exp" (expiration time) claim identifies the expiration time on
or after which the JWT MUST NOT be accepted for processing. The
processing of the "exp" claim requires that the current date/time
MUST be before the expiration date/time listed in the "exp" claim.

Implementers MAY provide for some small leeway, usually no more than
a few minutes, to account for clock skew. Its value MUST be a number
containing a NumericDate value. Use of this claim is OPTIONAL.

Another one to note would be the iat, which stands for issued at

The "iat" (issued at) claim identifies the time at which the JWT was
issued. This claim can be used to determine the age of the JWT. Its
value MUST be a number containing a NumericDate value. Use of this
claim is OPTIONAL.

A final one that could be used for time verfication, as far as I am aware of would be, nbf, standing for not before

The "nbf" (not before) claim identifies the time before which the JWT
MUST NOT be accepted for processing. The processing of the "nbf"
claim requires that the current date/time MUST be after or equal to
the not-before date/time listed in the "nbf" claim. Implementers MAY
provide for some small leeway, usually no more than a few minutes, to
account for clock skew. Its value MUST be a number containing a
NumericDate value. Use of this claim is OPTIONAL.

Now, for the code at hand, I don't see anything which is of, having following setup, this works perfectly fine for me

const jwt = require('jsonwebtoken');

const token = jwt.sign( {
hello: 'world'
}, 'myverysecretkey', {
expiresIn: '24h'
});

try {
const verify = jwt.verify( token, 'myverysecretkey' );
console.log( verify );
} catch (err) {
console.error( err );
}

which would output

Object {hello: "world", iat: 1557840459, exp: 1557926859}

This can be validated on the codesandbox link

Checking token expiration and log user out

so it turns out, i've been doing the check at the wrong place.

found out with some help that i could check under another function and here are the codes:

const ProtectedRoute = ({
component: Component,
roles = undefined,
...rest
}) => {
function isAuthActive() {
const user = JSON.parse(localStorage.getItem('User'));
const expiryTime = new Date(user?.expiration * 1000).toLocaleString(
'en-sg'
);
const currentTime = new Date().toLocaleString('en-sg');
if (expiryTime < currentTime) {
setCurrentUser();
localStorage.clear();
return <Redirect to="/login" />;
}
return true;
}
};

basically just checking current time against the expiry time given by the token. the rest are set in the backend server.

jwt.verify not throwing error for expired tokens

In your code you added expiresIn as part of the payload. But there expiresIn has no meaning and you need to use the standard expclaim for expiration:

jwt.sign({
id: 'an id',
exp: Math.floor(Date.now() / 1000) + (60 * 2),
iat: Math.floor(Date.now())
}, 'secret')

in this example it's 2 minutes.
You can also calculate:
(60 * minutes), (3600 * hours) or (86400 * days) for minutes, hours or days.

expiresIn can be used as an option to the sign method as shown in Shivam Soods answer. I think that's the reason for your confusion.



Related Topics



Leave a reply



Submit