A JSON Web Token (JWT) is a compact, URL-safe way to carry signed claims between two parties — most often between an authentication server and your API. If you have ever inspected an Authorization: Bearer ... header and seen a long string with two dots in it, that is a JWT. This guide shows you how to read one, what each part means, and the single most important security rule: decoding is not verifying.
You can paste any token into our JWT decoder to follow along — it runs entirely in your browser and never transmits your token.
What are the three parts of a JWT?
A signed JWT (technically a JWS) has exactly three parts separated by dots:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjMiLCJleHAiOjE3ODA0MDB9.Qm9iSXNNeUF1bnQ
└──── header ────┘ └──────── payload ────────┘ └─ signature ─┘
| Part | What it holds | Encoding |
|---|---|---|
| Header | The signing algorithm (alg) and token type (typ) | Base64URL JSON |
| Payload | The claims — data about the user and token | Base64URL JSON |
| Signature | A keyed hash of header.payload | Base64URL bytes |
The first two parts are just Base64URL-encoded JSON. They are not encrypted. Anyone who has the token can decode and read them, which is the whole point of this article.
How do you decode a JWT by hand?
To decode the header or payload manually:
- Split the string on the dots into three pieces.
- Take the first piece (header) or second piece (payload).
- Base64URL-decode it. Base64URL is standard Base64 with
+→-,/→_, and the=padding removed. - Read the resulting JSON.
Because Base64URL drops padding, you may need to re-add = characters until the length is a multiple of four before a standard Base64 decoder will accept it. If you would rather not do this in your head, the JWT decoder handles the padding and pretty-prints the JSON for you, and our Base64 encode/decode tool explains the alphabet difference in detail.
What do the standard JWT claims mean?
The payload is a set of claims. Some are registered (standardised in RFC 7519); the rest are application-defined. The most common registered claims:
| Claim | Name | Meaning |
|---|---|---|
iss | Issuer | Who created and signed the token |
sub | Subject | Who the token is about (usually a user id) |
aud | Audience | Who the token is intended for |
exp | Expiration | Reject after this Unix time (seconds) |
nbf | Not before | Reject before this Unix time |
iat | Issued at | When the token was created |
jti | JWT ID | Unique identifier, useful for revocation lists |
The time claims (exp, nbf, iat) are Unix timestamps in seconds. If you want to translate one into a human-readable date, drop it into the Unix timestamp converter.
Why should you never trust an unverified JWT?
Here is the part developers get wrong. Decoding the payload tells you what the token claims, but a token is trivial to fabricate or edit because the payload is plain Base64URL. The only thing standing between a real token and a forged one is the signature.
Verification means:
- Recomputing the signature over
header.payloadusing the secret key (for HMAC algorithms likeHS256) or the issuer’s public key (for asymmetric algorithms likeRS256/ES256). - Confirming the recomputed signature matches the one in the token.
- Checking that
exphas not passed andnbfhas been reached.
If you skip verification and act on a decoded claim like "role": "admin", an attacker can simply edit that claim and re-encode the payload. Real-world classes of attack make this concrete:
- The
alg: noneattack. Older libraries accepted a header that declared no algorithm and treated the token as valid with an empty signature. Always rejectnoneexplicitly. - Algorithm confusion (RS256 → HS256). An attacker switches the header to
HS256and signs with the public RSA key as if it were an HMAC secret. Pin the expected algorithm; do not let the token choose it.
Because signature verification needs your secret or private key, it must happen server-side. Never paste a signing secret into a web page, and never verify in client-side JavaScript that ships the key to the browser.
Decode vs. verify at a glance
| Decode | Verify | |
|---|---|---|
| What it does | Reads header + payload | Confirms authenticity + integrity |
| Needs a key? | No | Yes (secret or public key) |
| Proves the token is genuine? | No | Yes |
| Where to do it | Anywhere (browser is fine) | Server only |
| Tool | JWT decoder | Your backend auth library |
Practical checklist
- Inspect freely, trust never. Use a decoder to debug, but make authorization decisions only on verified tokens.
- Pin the algorithm. Configure your library to accept exactly the algorithms you issue.
- Validate
exp,nbf,aud, andisson every request, not just the signature. - Keep payloads lean and non-secret. Anyone can read them. The mechanics of why are the same one-way-vs-reversible distinction we cover in hashing vs encryption vs encoding.
- Rotate and revoke. Short
explifetimes plus ajtidenylist limit the damage of a leaked token.
Sources
- IETF RFC 7519, JSON Web Token (JWT).
- IETF RFC 7515, JSON Web Signature (JWS).
- OWASP, JSON Web Token for Java Cheat Sheet (algorithm-confusion and
alg:noneguidance).