JWT tokens: what's hiding behind “eyJhbGciOi…” and how to read it
You open developer tools and see this in the Authorization header: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ… Long, cryptic, looks like a cipher. It's actually a JWT (JSON Web Token) — a user's “passport” that a service issues after login. And its defining feature is that you can read the contents without any keys at all.
Three parts separated by dots
A JWT consists of three sections separated by dots: the header, the payload, and the signature. Each section is encoded in base64url — a URL-safe variety of Base64. Let's decode the first part of the token above:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
→ {"alg":"HS256","typ":"JWT"}That's the header: the token is signed with the HS256 algorithm and is a JWT. This also explains why every JWT starts with “eyJ”: in base64url, the sequence {" always produces exactly those characters. The middle part — the payload — decodes the same way and carries the data: who the user is, what they're allowed to do, and when the token expires (the exp field).
Signed does not mean encrypted
Here's the key misconception: “the token is long and unreadable, so the data must be protected.” No. Anyone can read the payload — Base64 decodes in a second. The signature (the third part) solves a different problem: it guarantees the token hasn't been tampered with — the server verifies it with its secret key. Changing the contents is pointless: the signature will no longer match. But reading it? Nobody's stopping you.
From this follow a few practical rules: never put secrets in the payload (passwords, card numbers, personal data) — anything in the token, the user can see; check exp — a token has a limited lifetime, and that's a good thing; HS256 uses a single shared secret for signer and verifier, while RS256 uses a key pair (the more convenient choice for microservices).
How to look inside a token
Paste the token into the JWT decoder: the header and payload unfold into readable JSON, and the exp and iat fields are converted into dates. All decoding happens in your browser — the token is never sent anywhere, which matters: a token is exactly what a user authenticates with. We covered the base64 mechanics behind all this in our article on Base64.