Les pubs vous déplaisent ? Aller Sans pub Auj.

JWT Tokens Décoder, vérifier et éviter les erreurs courantes

Publié le
JWT Tokens: Decode, Verify, and Avoid Common Mistakes 1
ANNONCE · Supprimer ?
JWT Tokens: Decode, Verify, and Avoid Common Mistakes

JWTs show up in virtually every modern web app — auth headers, refresh flows, API access control. They’re also one of the most consistently misused standards in the wild. If you’re building with them, understanding what’s inside the token, what decoding versus verifying actually means, and which shortcuts quietly break your security is non-negotiable.

The Anatomy of a JWT

A JWT is three base64url-encoded strings joined by dots:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyXzEyMyIsImVtYWlsIjoiYWxpY2VAZXhhbXBsZS5jb20iLCJpYXQiOjE3MTI3NjQ4MDAsImV4cCI6MTcxMjg1MTIwMH0.4Xr8mNkZQWpH2TvL9uY3sKdJwFqBzEcAoMnRiVePxlU
  • En-tête — algorithm and token type (alg, typ)
  • Charge utile — the claims (data your app actually needs)
  • Signature — HMAC or RSA signature over the first two parts

Decoded, that payload looks like this:

{
  "sub": "user_123",
  "email": "alice@example.com",
  "iat": 1712764800,
  "exp": 1712851200
}

Nothing here is encrypted. Anyone holding the token can read these values. The signature only proves the token wasn’t tampered with after it was issued — it doesn’t hide the contents.

Decoding Is Not Verifying

This distinction trips up more developers than it should.

Decoding splits the token at the dots and base64url-decodes each section. No secret needed — any tool or one-liner can do it. If you want to jwt decode online without installing anything, paste the token into IO Tools JWT Decoder and get the header, payload, and expiry breakdown instantly.

Verifying checks that the signature is valid using the secret (or public key for asymmetric algorithms). It also confirms the token hasn’t expired and that the claims match what your application expects. Skipping verification and trusting a decoded token is how authentication bypasses happen.

Here’s a Node.js snippet that verifies a JWT and handles the common edge cases:

import jwt from 'jsonwebtoken';

const SECRET = process.env.JWT_SECRET;

function verifyToken(token) {
  try {
    const payload = jwt.verify(token, SECRET, {
      algorithms: ['HS256'],  // whitelist — never allow 'none'
      audience: 'myapp',      // validate aud claim
    });

    // jwt.verify throws if exp is in the past, but be explicit:
    if (payload.exp < Math.floor(Date.now() / 1000)) {
      throw new Error('Token expired');
    }

    return payload;
  } catch (err) {
    // Never silently swallow verification failures
    throw new Error(`Invalid token: ${err.message}`);
  }
}

Claims Worth Validating

The JWT spec defines standard claims your server should actively check, not just read:

RevendicationSignificationValidate it?
expExpiration timestampAlways — stale tokens are a real attack surface
iatIssued-at timestampOptional, useful for max-age checks
subSubject (usually user ID)Yes — confirm it matches the expected user
audIntended audienceYes — prevents tokens for service A being used on service B

Most JWT libraries validate exp automatically — but only if you configure them to. Read your library’s docs. Don’t assume it’s on by default.

Three Mistakes That Get Developers Burned

1. The alg: none Attaque

The JWT spec allows an algorithm value of none, meaning no signature. Some libraries — particularly older ones — accept this and skip signature verification entirely. An attacker strips the signature, sets "alg": "none" in the header, and forges arbitrary claims. The server trusts it.

Fix: explicitly whitelist algorithms when verifying. Never accept none. The snippet above demonstrates this with algorithms: ['HS256'].

2. Not Validating Expiry

Decoding a token and trusting the payload without checking exp means a token issued months ago is still accepted. If a user’s session was revoked or an attacker stole an old token, your application would never know.

Fix: treat expiry as mandatory, not optional. To check when a specific token runs out, IO Tools JWT Expiry Checker decodes the exp claim and tells you exactly how much time is left — useful for debugging refresh flows without writing code.

3. Storing JWTs in localStorage

localStorage is readable by any JavaScript on the page. A single XSS vulnerability means an attacker can exfiltrate your user’s auth token silently. Here’s how the storage options compare:

StorageXSS riskCSRF riskAccessible from JSRemarques
localStorageHautAucunOuiAvoid for auth tokens
sessionStorageHautAucunOuiSame risks as localStorage
httpOnly cookieAucunMoyenNonBest for auth; pair with SameSite + CSRF token
In-memory (JS var)FaibleAucunYes (same context)Lost on refresh; fine for short-lived tokens

httpOnly cookies can’t be read by JavaScript at all, which eliminates the XSS theft vector entirely. The trade-off is CSRF exposure, which you handle with SameSite=Strict or a CSRF token.

JWTs vs Sessions: The Honest Trade-off

JWTs are stateless — the server validates them without querying a database. That’s useful in distributed systems where you don’t want every service hitting a shared session store.

But stateless has a real cost: you can’t revoke a JWT before it expires. If a user logs out or is compromised, the token remains valid until exp. Workarounds (token blocklists, short expiry + refresh tokens) exist, but they add complexity and often recreate what a session store already does.

Use JWTs when: you have multiple services authenticating requests independently, you want to embed roles/permissions directly in the token, or your tokens are short-lived and revocation latency is acceptable.

Use sessions when: you need immediate revocation (logout should actually work), you’re building a server-rendered app, or simplicity outweighs stateless scalability.

Inspect a Token in Seconds

Need to see what’s inside a JWT right now? Terminal:

echo "YOUR.JWT.HERE" | cut -d. -f2 | base64 -d 2>/dev/null | python3 -m json.tool

Or skip the terminal — paste the token into IO Tools JWT Decoder to get a formatted breakdown of the header and payload. Neither approach verifies the signature; they decode. For a quick expiry read without writing code, the JWT Expiry Checker gives you the exact timestamp and time remaining.

Envie d'une expérience sans pub ? Passez à la version sans pub

Installez nos extensions

Ajoutez des outils IO à votre navigateur préféré pour un accès instantané et une recherche plus rapide

Sur Extension Chrome Sur Extension de bord Sur Extension Firefox Sur Extension de l'opéra

Le Tableau de Bord Est Arrivé !

Tableau de Bord est une façon amusante de suivre vos jeux, toutes les données sont stockées dans votre navigateur. D'autres fonctionnalités arrivent bientôt !

ANNONCE · Supprimer ?
ANNONCE · Supprimer ?
ANNONCE · Supprimer ?

Coin des nouvelles avec points forts techniques

Impliquez-vous

Aidez-nous à continuer à fournir des outils gratuits et précieux

Offre-moi un café
ANNONCE · Supprimer ?