Check if token expired using this JWT library

Javascriptnode.jsExpressJwt

Javascript 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') 
    }
  }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndr&#233;s MontoyaView Question on Stackoverflow
Solution 1 - JavascriptAndrés MontoyaView Answer on Stackoverflow
Solution 2 - JavascriptGabriel BleuView Answer on Stackoverflow
Solution 3 - JavascriptEmanuelView Answer on Stackoverflow
Solution 4 - JavascriptRashomonView Answer on Stackoverflow
Solution 5 - JavascriptlonyView Answer on Stackoverflow
Solution 6 - JavascriptSandroView Answer on Stackoverflow
Solution 7 - JavascriptgauravsbagulView Answer on Stackoverflow
Solution 8 - JavascriptSehrish WaheedView Answer on Stackoverflow
Solution 9 - JavascriptNimaView Answer on Stackoverflow
Solution 10 - JavascriptZaurView Answer on Stackoverflow