How toValidate exp, iat, and nbf in JWTs

When using JWTs as access tokens in OAuth2, it's important to verify when the token is valid—and when it isn’t.

There are three standard claims used to control token timing:

  • exp (expiration): when the token expires
  • nbf (not before): when the token becomes valid
  • iat (issued at): when the token was created

Verifying exp with @edgefirst-dev/jwt

When using the JWT.verify() method from @edgefirst-dev/jwt, the library automatically checks the exp claim:

const token = await JWT.verify(accessToken, jwks, {
  issuer: "https://example.com",
  audience: "https://api.example.com",
});

If the token has expired, this method will throw.

Manually validating nbf and iat

The nbf (not before) and iat (issued at) claims are not automatically validated, but you can easily add your own checks:

if (token.nbf && Date.now() / 1000 < token.nbf) {
  throw new Error("Token not yet valid");
}

if (token.iat && Date.now() / 1000 < token.iat) {
  throw new Error("Token issued in the future");
}

Note: the comparison uses Date.now() / 1000 because JWT timestamps are in seconds, not milliseconds.

Validating these claims helps you avoid accepting tokens that are expired, not yet valid, or potentially forged with an invalid iat.

It’s a small step that improves your API’s security and predictability.


I'm currently writing a book called React Router OAuth2 Handbook, focused on implementing secure OAuth2 authentication in Remix and React Router apps—using patterns you can apply to any web app.

The landing page is live (book coming soon) at books.sergiodxa.com.