JWTs: What's Actually in Those Long Strings
JSON Web Tokens decoded. How they work, what they contain, and common security mistakes.
You see a string like eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U in your auth system.
What is that? It's a JWT—three Base64-encoded chunks separated by dots. And you can read it without any special keys.
The Three Parts
Header: Algorithm and token type
{"alg": "HS256", "typ": "JWT"}
Payload: The actual data (claims)
{"sub": "1234567890", "name": "John", "iat": 1516239022}
Signature: Verification that nothing was tampered with
JWTs Are Not Encrypted
This is the big one. Anyone can decode a JWT and read its contents. Base64 is encoding, not encryption.
Don't put secrets in JWTs. User IDs, permissions, expiration times—fine. Passwords, credit cards, private data—never.
Standard Claims
iss — Issuer. Who created this token.
sub — Subject. Usually the user ID.
exp — Expiration. Unix timestamp when the token becomes invalid.
iat — Issued at. When the token was created.
aud — Audience. Who should accept this token.
Custom claims work too. Add whatever data your application needs.
How Signatures Work
The signature proves the token hasn't been modified.
Server creates token → signs with secret key → sends to client. Client sends token back → server verifies signature → trusts the content.
If someone changes the payload, the signature won't match. The server rejects it.
But the server must verify the signature. JWTs without verification are security theater.
Common Security Mistakes
Not verifying signatures. Some code decodes JWTs without checking the signature. Anyone can forge tokens.
Using weak secrets. secret123 is not a secret. Use long, random strings.
Ignoring expiration. Always check exp. Tokens should have short lifetimes.
Algorithm confusion. The alg field says how to verify. Attackers can set it to none and skip verification if your code trusts the header.
Storing sensitive data. Anyone with the token can read the payload. Keep secrets server-side.
When to Use JWTs
Stateless authentication. Server doesn't need to store sessions. The token contains everything needed.
Microservices. Services can verify tokens without calling the auth server.
Single sign-on. Share authentication across domains.
When Not to Use JWTs
Simple apps. Session cookies are simpler and harder to mess up.
Need to invalidate immediately. JWTs are valid until expiration. Revoking requires extra infrastructure.
Large payloads. Every request carries the full token. Big tokens mean more bandwidth.
Refresh Tokens
Access tokens should be short-lived (minutes to hours). Refresh tokens get new access tokens without re-authentication.
Store refresh tokens securely. They're long-lived and powerful.
JWTs are convenient but require care. Understand what they contain, verify signatures properly, set short expirations, and never put sensitive data in the payload.