'Check if token expired using this JWT library
I've configured the token like this:
jwt.sign(
{
user: pick(user, ['_id', 'username'])
},
secret,
{
expiresIn: '2m'
}
);
But when I want to check if the token was expired, this code doesn't work:
function isAuthenticated() {
const token = localStorage.getItem('token');
const refreshToken = localStorage.getItem('refreshToken');
try {
decode(token);
const { exp } = decode(refreshToken);
if (exp < (new Date().getTime() + 1) / 1000) {
return false;
}
} catch (err) {
return false;
}
return true;
}
The problem is this part:
if (exp < (new Date().getTime() + 1) / 1000) {
return false;
}
new Date().getTime() + 1) / 1000 = 1531335468.113
exp = 1531334595
Because I don't know what format of time JWT uses...
How can I resolve this?
Solution 1:[1]
You should use jwt.verify. It will check if the token is expired.
jwt.decode should not be used if the source is not trusted as it doesn't check if the token is valid.
Solution 2:[2]
Function without the jwt library:
Browser
function isTokenExpired(token) {
const base64Url = token.split(".")[1];
const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
const jsonPayload = decodeURIComponent(
atob(base64)
.split("")
.map(function (c) {
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
})
.join("")
);
const { exp } = JSON.parse(jsonPayload);
const expired = Date.now() >= exp * 1000
return expired
}
Or simpler
function isTokenExpired(token) {
const expiry = (JSON.parse(atob(token.split('.')[1]))).exp;
return (Math.floor((new Date).getTime() / 1000)) >= expiry;
}
Or a one-liner:
const isTokenExpired = token => Date.now() >= (JSON.parse(atob(token.split('.')[1]))).exp * 1000
Node.js
function isTokenExpired(token) {
const payloadBase64 = token.split('.')[1];
const decodedJson = Buffer.from(payloadBase64, 'base64').toString();
const decoded = JSON.parse(decodedJson)
const exp = decoded.exp;
const expired = (Date.now() >= exp * 1000)
return expired
}
Or a one-liner:
const isTokenExpired = (token) => (Date.now() >= JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()).exp * 1000)
Solution 3:[3]
verify itself returns an error if expired. It is safer as Gabriel said.
const jwt = require('jsonwebtoken')
router.use((req, res, next) => {
const token = yourJwtService.getToken(req) // Get your token from the request
jwt.verify(token, req.app.get('your-secret'), function(err, decoded) {
if (err) throw new Error(err) // Manage different errors here (Expired, untrusted...)
req.auth = decoded // If no error, token info is returned in 'decoded'
next()
});
})
And same written in async/await syntax:
const jwt = require('jsonwebtoken')
const util = require('util');
const jwtVerifyAsync = util.promisify(jwt.verify);
router.use(async (req, res, next) => {
const token = yourJwtService.getToken(req) // Get your token from the request
try {
req.auth = await jwtVerifyAsync(token, req.app.get('your-secret')) // If no error, token info is returned
} catch (err) {
throw new Error(err) // Manage different errors here (Expired, untrusted...)
}
next()
});
Solution 4:[4]
Sadly, Andrés Montoya's answer has a flaw which is related to how he compares the object.
I found a solution here which should solve this:
const now = Date.now().valueOf() / 1000
if (typeof decoded.exp !== 'undefined' && decoded.exp < now) {
throw new Error(`token expired: ${JSON.stringify(decoded)}`)
}
if (typeof decoded.nbf !== 'undefined' && decoded.nbf > now) {
throw new Error(`token expired: ${JSON.stringify(decoded)}`)
}
Thanks to user thejohnfreeman!
Solution 5:[5]
The following function works without any libraries:
function getJWTExpireDate(jwtToken: string) {
if (jwtToken) {
try {
const [, payload] = jwtToken.split('.');
const { exp: expires } = JSON.parse(window.atob(payload));
if (typeof expires === 'number') {
return new Date(expires * 1000);
}
} catch {
// ignore
}
}
return null;
}
Don't use this to check whether the token is valid. One good use case is displaying when the token expires in the frontend.
Solution 6:[6]
This is for React Native, but login will work for all types.
isTokenExpired = async () => {
try {
const LoginTokenValue = await AsyncStorage.getItem('LoginTokenValue');
if (JSON.parse(LoginTokenValue).RememberMe) {
const { exp } = JwtDecode(LoginTokenValue);
if (exp < (new Date().getTime() + 1) / 1000) {
this.handleSetTimeout();
return false;
} else {
//Navigate inside the application
return true;
}
} else {
//Navigate to the login page
}
} catch (err) {
console.log('Spalsh -> isTokenExpired -> err', err);
//Navigate to the login page
return false;
}
}
Solution 7:[7]
You can use the jwt verify method to check the validity of your token. err means the token is expired and will throw an error so you can remove the stored token.
jwt.verify(token, SECRET, (err, decoded) => {
if (err) {
localStorage.clear();
}}
});
Solution 8:[8]
const JWT = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEyMzQ1Njc4OTAsIm5hbWUiOiJKb2huIERvZSIsImlhdCI6MTUxNjIzOTAyMn0.1c_yQjnMZfKUb4UTDE_WvbC71f8xxtyMsdqKKkI1hF8";
const jwtPayload = JSON.parse(window.atob(JWT.split('.')[1]))
const isExpired = Date.now() >= jwtPayload.exp * 1000;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
