Decoding and Understanding JWTs

What a JSON Web Token contains, how its three parts fit together, the difference between decoding and verifying, and the security rules that matter.

Updated July 2026 · 7 min read

JSON Web Tokens (JWTs) are everywhere in modern authentication: log in to almost any web app and a JWT is probably riding along in your requests. They look like an opaque blob of characters, but they are surprisingly readable once you understand their structure. This guide explains what is inside a JWT, the crucial difference between decoding and verifying, and the security rules that keep you out of trouble.

The three parts

A JWT is three Base64URL-encoded sections joined by dots:

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjMiLCJuYW1lIjoiQWRhIn0.SflKxw...
└──── header ────┘ └──────── payload ────────┘ └ signature ┘
  • Header — describes the token type and the signing algorithm, e.g. { "alg": "HS256", "typ": "JWT" }.
  • Payload — the claims: who the user is, what they can do, and when the token expires.
  • Signature — a cryptographic hash of the header and payload, computed with a secret (HS256) or a private key (RS256). It proves the token has not been altered.

Decoding vs. verifying

This is the single most important distinction to understand:

  • Decoding is just Base64URL-decoding the header and payload into readable JSON. Anyone holding the token can do it — no secret required. That is exactly what a JWT decoder does, and why you must never store sensitive data in the payload.
  • Verifying recomputes the signature using the secret or public key and checks it against the token's signature. Only a party with the key can do this, and it is what actually proves the token is authentic. Verification always happens on the server.
A decoder tells you what a token claims. Only verification tells you whether to believe it.

Reading the payload

A decoded payload might look like this:

{
  "sub": "1234567890",
  "name": "Ada Lovelace",
  "role": "admin",
  "iat": 1735689600,
  "exp": 1735693200
}

Several claim names are standardized:

ClaimMeaning
subSubject — who the token is about (usually a user ID).
issIssuer — the service that created the token.
audAudience — who the token is intended for.
iatIssued at — creation time as a Unix timestamp.
expExpiration — the token is invalid after this time.

Everything else — role, name, scope — is a custom claim your application defines. Because timestamps are in seconds, an exp of 1735693200 is easy to check but not human-readable at a glance; a decoder that converts it to a date saves you the arithmetic.

Security rules that matter

  • Never trust an unverified token. On the server, always verify the signature before reading any claim.
  • Never put secrets in the payload. It is readable by anyone with the token.
  • Reject the none algorithm. A token whose header says "alg": "none" has no signature; a correctly configured server refuses it.
  • Check expiration. Verification libraries reject expired tokens automatically, but only if you actually call them.
  • Keep tokens short-lived. Pair a short-lived access token with a longer-lived refresh token so a leaked token has a small blast radius.

A debugging workflow

  1. Decode the token to read its header and payload.
  2. Confirm the algorithm in the header is what you expect (and not none).
  3. Check exp against the current time to see whether the token is still valid.
  4. Confirm the custom claims (role, scope) match what your app requires.
  5. If authentication still fails, the problem is usually signature verification on the server, not the token contents.

Try it

The DevBox JWT Decoder splits a token into its header, payload, and signature and pretty-prints the claims — all in your browser, so the token never leaves your machine. Since each part is Base64URL-encoded, the Base64 guide is a useful companion.

Frequently asked questions

Is decoding a JWT the same as verifying it?+

No. Decoding just Base64URL-decodes the header and payload so you can read them — anyone can do this. Verifying checks the signature against a secret or public key to prove the token is authentic and unaltered. Only the server that holds the key can verify.

Is the payload of a JWT encrypted?+

No. A standard JWT is signed, not encrypted. The payload is only Base64URL-encoded, so anyone who has the token can read its claims. Never put passwords or secrets in a JWT payload.

What do exp and iat mean?+

They are standard claims expressed as Unix timestamps (seconds since 1970). iat is 'issued at' — when the token was created. exp is 'expiration' — after this time the token should be rejected.

Why are there three parts separated by dots?+

A JWT is header.payload.signature. The header describes the signing algorithm, the payload holds the claims, and the signature is computed over the first two parts so tampering can be detected.

Is it safe to paste a JWT into an online decoder?+

Use a decoder that runs entirely in your browser, like DevBox's, so the token is never sent to a server. Even then, avoid pasting production tokens that grant real access — decode test tokens during development.