Skip to content
dz / jwt-expired-check
Security · JWT decoder

Check if a JWT is expired

Paste the token – the box under it turns red with "Expired 3 h ago", amber when it is not valid yet, and green while it is still valid.

/jwt

Signature

Everything runs in your browser – the token and your keys are never sent anywhere and not stored. Still, treat a production token like a password.

Header algorithm & token type
Payload claims – editable
Set
Claims

How "expired" is decided

A token is expired when the current time is at or after its exp claim, and not yet valid while the time is before nbf. The example token was issued at 2025-01-01 00:00 UTC with a one-hour lifetime, so it expired at 01:00 that day.

Servers usually allow a small clock skew – often 30 to 60 seconds – so a token that expired a few seconds ago may still be accepted by one service and rejected by another. If a fresh token is rejected as "not yet valid", the issuer's clock is probably ahead of the server's.

Checking it in code

// JavaScript – decode without verifying, compare with now (seconds)
const { exp } = JSON.parse(atob(token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/')));
const expired = exp !== undefined && Date.now() / 1000 >= exp;

// Node with the "jose" library – verifies the signature AND exp / nbf
await jwtVerify(token, key, { clockTolerance: '30s' });   // throws JWTExpired

Only the second form is safe on a server: an expiry you read without verifying the signature can be forged.

Questions

My token has no exp – is it valid forever?

Technically yes, and that is a security risk: a leaked token can be used until the key is rotated. Access tokens should expire within minutes to an hour.

How do I get a new token when it expires?

With OAuth 2.0 / OpenID Connect the client uses its refresh token to request a new access token. Simply changing exp does not work – the signature would no longer match.

Can I make an expired test token?

Yes – press exp = expired under the payload. With the secret or private key entered, the tool re-signs the token so you can test that your API rejects it.

▸ About this tool

About the JWT Decoder

Introduction

A JSON Web Token (JWT, RFC 7519) is the compact, URL-safe token that most APIs, single sign-on systems and OAuth 2.0 / OpenID Connect providers use to say who you are and what you may do. This tool decodes a token into its header and claims, tells you whether it is expired, verifies its signature with a secret or public key, and lets you edit the claims and sign a new token – handy for debugging authentication, testing how an API handles expired or tampered tokens, and learning how JWTs work.

How to use it

  1. Paste a token into Encoded token. A leading Bearer or a whole Authorization: header line is removed automatically.

  2. Read the header and payload on the right. Time claims (exp, nbf, iat, auth_time) are shown as UTC dates with "in 5 min" / "3 h ago", and the box under the token says whether it is valid right now.

  3. To check the signature, enter the secret (HS256/384/512) or paste the public key (RS*, PS*, ES*, EdDSA) as PEM, X.509 certificate, JWK or a whole JWKS – the right key is picked by the token's kid.

  4. Edit the header or payload, or use the Set buttons for iat, exp and nbf. The token is re-encoded immediately; with the secret or private key it is re-signed too, otherwise the old signature is struck through because it no longer matches.

Short links: develzone.org/jwt, /jws and /bearer. Pasting a token into the search box on any page opens it here.

Anatomy of a token

A signed JWT has three Base64url parts separated by dots, shown in three colours:

  • Header – the algorithm (alg), usually the type (typ: "JWT") and often a key ID (kid).

  • Payload – the claims: registered ones such as issuer (iss), subject (sub), audience (aud), expiry (exp), plus anything the issuer adds – roles, scopes, e-mail.

  • Signature – computed over header.payload with a secret or private key. Change one character of the first two parts and it no longer matches.

The payload is only encoded, not encrypted – anyone holding the token can read it. Never put passwords or secrets into claims. Tokens with five parts are encrypted (JWE); their payload cannot be read without the recipient's key.

Supported algorithms

  • HS256, HS384, HS512 – HMAC with one shared secret. Use at least as many random bytes as the hash size (32 for HS256).

  • RS256, RS384, RS512 and PS256, PS384, PS512 – RSA signatures (PKCS#1 v1.5 and PSS).

  • ES256, ES384, ES512 – ECDSA on the P-256, P-384 and P-521 curves.

  • EdDSA (Ed25519) – needs a current browser.

Keys are accepted as SPKI / PKCS#8 PEM, X.509 certificates, JWK and JWKS. Old PKCS#1 (BEGIN RSA PRIVATE KEY) and SEC1 PEMs are not – the tool tells you the openssl command to convert them.

Good to know

  • A decoded token proves nothing until its signature is verified with a key you trust, and exp, nbf, iss and aud are checked. Servers must reject alg: "none".

  • Times are in seconds since 1970 (UTC). Convert any of them with the Unix timestamp converter.

  • Just need one part decoded? The Base64url decoder does that.

Privacy

Decoding, verifying and signing all happen in your browser with the Web Crypto API. Tokens, secrets and keys are never sent to a server and not stored; a token passed in a link is removed from the address bar as soon as the page has read it. Still, treat production tokens like passwords – they are valid credentials until they expire.

❯ Esc
↑ ↓ select ↵ open Shift ↵ new line