dev cosmos/ blog/ jwt-decoder-guide

JWT Decoded: Understanding JSON Web Tokens from Header to Signature

A practical deep dive into JWT structure, registered claims, expiry logic, security pitfalls, and how to debug tokens with confidence.

JWT

JWT Decoder

Header · Payload · Signature

JSON Web Tokens are the de facto standard for authentication tokens in modern APIs. They're compact, self-contained, and URL-safe — but they're also frequently misunderstood and misused. This guide walks through every component of a JWT so you can read, debug, and reason about them with full confidence.

JWT
Open in Dev Cosmos
JWT Decoder & Inspector →

What Is a JWT?

A JSON Web Token (RFC 7519) is a compact, URL-safe string that encodes a set of claims — assertions about a subject (typically a logged-in user). It has three Base64URL-encoded parts separated by dots:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIiwiaWF0IjoxNzA1MzE4MjAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

The three parts are: header · payload · signature. The Dev Cosmos JWT Decoder colour-codes each part exactly this way.

The header is a JSON object that specifies the token type and signing algorithm:

{
  "alg": "HS256",   // Signing algorithm
  "typ": "JWT"      // Token type
}

Common algorithms:

AlgorithmTypeUse Case
HS256Symmetric (HMAC)Single-server — same key signs and verifies
RS256Asymmetric (RSA)Multi-service — private key signs, public key verifies
ES256Asymmetric (ECDSA)Same as RS256 but shorter keys, faster
noneNo signatureDevelopment only — never in production
🚨
The "alg: none" Attack
Some older JWT libraries accepted "alg": "none" and skipped signature verification entirely. An attacker could forge any token. Always verify the algorithm in your server-side code and reject none.

The Payload

The payload contains claims — key-value pairs about the token subject. There are three types:

Registered Claims (Standard)

ClaimFull NameDescription
issIssuerWho created and signed the token (e.g. "auth.myapp.com")
subSubjectWho the token refers to (usually a user ID)
audAudienceWho the token is intended for (e.g. "api.myapp.com")
expExpirationUnix timestamp after which the token is invalid
nbfNot BeforeUnix timestamp before which the token is not valid
iatIssued AtUnix timestamp when the token was created
jtiJWT IDUnique identifier — used to prevent replay attacks

Private Claims (Custom)

Your application can add any custom claims:

{
  "sub": "user_1234",
  "email": "alice@example.com",
  "role": "admin",
  "permissions": ["read:orders", "write:products"],
  "iat": 1705318200,
  "exp": 1768476800
}
⚠️
Don't Store Sensitive Data in JWTs
JWT payloads are Base64-encoded, not encrypted. Anyone with the token can read the payload instantly. Never store passwords, payment details, or PII in a JWT unless you also encrypt it (JWE).

The Signature

The signature is a cryptographic MAC (Message Authentication Code) over the header and payload. It's computed as:

HMACSHA256(
  base64url(header) + "." + base64url(payload),
  secret
)

The server verifies the signature on every request to confirm the token hasn't been tampered with. If anyone changes even one character of the payload, the signature becomes invalid.

ℹ️
Client-Side Decoding Only
The Dev Cosmos JWT Decoder (and any client-side tool) can only decode the header and payload — it cannot verify the signature, because it doesn't have your secret key. Signature verification must be done server-side with the appropriate library.

Expiry and the Progress Bar

The decoder shows a visual progress bar between iat (issued at) and exp (expiry). The bar turns amber when more than 70% of the token's lifetime has elapsed, and red when over 90%. This gives you an instant visual of how long the token has left.

When debugging authentication failures, expiry is the first thing to check. A 401 from your API almost always means an expired token on the client side.

JWT Security Best Practices

  • Short expiry times — 15 minutes for access tokens, 7–30 days for refresh tokens. Shorter tokens limit the damage window if a token is stolen.
  • Use RS256 in distributed systems — with asymmetric signing, downstream services only need the public key to verify tokens, not your private signing secret.
  • Store tokens securely — use httpOnly cookies to prevent XSS access. Avoid localStorage for sensitive tokens.
  • Implement token revocation — stateless JWTs can't be invalidated before expiry without a revocation list (blocklist). Design your auth flow accordingly.
  • Validate all claims — check iss, aud, and exp on every request. Don't trust a valid signature alone.

Debugging Workflow

  1. Copy the token from your browser's DevTools (Network tab → request headers → Authorization: Bearer ...)
  2. Paste into the Dev Cosmos JWT Decoder
  3. Check the expiry progress bar — is it expired?
  4. Inspect the payload claims — correct user ID? correct role?
  5. Verify the algorithm in the header matches what your server expects
JWT
Open in Dev Cosmos
JWT Decoder & Inspector →
More from the Blog