Check if token expired using this JWT library
Javascriptnode.jsExpressJwtJavascript Problem Overview
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?
Javascript Solutions
Solution 1 - Javascript
This is the answer:
if (Date.now() >= exp * 1000) {
return false;
}
Solution 2 - Javascript
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 3 - Javascript
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 4 - Javascript
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 5 - Javascript
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 6 - Javascript
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 7 - Javascript
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 8 - Javascript
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 9 - Javascript
const JWT = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEyMzQ1Njc4OTAsIm5hbWUiOiJKb2huIERvZSIsImlhdCI6MTUxNjIzOTAyMn0.1c_yQjnMZfKUb4UTDE_WvbC71f8xxtyMsdqKKkI1hF8";
const jwtPayload = JSON.parse(window.atob(JWT.split('.')[1]))
const isExpired = Date.now() >= jwtPayload.exp * 1000;
Solution 10 - Javascript
// Pass in function expiration date to check token
function checkToken(exp) {
if (Date.now() <= exp * 1000) {
console.log(true, 'token is not expired')
} else {
console.log(false, 'token is expired')
}
}