I work in fintech, and the gap between what developers assume JWT does and what it actually does has caused real damage — leaked user data, privacy issues, compliance headaches.
JWT is a container, not a lock
JWT is a format.
Three base64-encoded parts:
- header
- payload
- optional signature
Separated by dots.
That's it.
It gives structure to data in transit. It does not hide anything.
Anyone holding a JWT can decode the payload in seconds without any key.
It looks cryptographic — which is exactly why people trust it more than they should.
Three flavors, and most people only know one
Unsigned JWT (alg: none)
No signature, no integrity check.
The spec allows it. Your server shouldn't.
JWS (signed) What nearly everyone actually means when they say "JWT".
- The payload is fully readable
- The signature proves it hasn't been tampered with
Think:
Tamper-proof envelope, clear plastic
JWE (encrypted) The only variant that actually hides the payload.
Less common, but the only one that provides real confidentiality.
How JWE works under the hood
JWE uses hybrid encryption:
- A random content encryption key (CEK) encrypts the payload (fast, symmetric — e.g. AES)
- The CEK itself is encrypted using the receiver's public key
- Both are included in the token
Only the holder of the private key can:
- Decrypt the CEK
- Use it to decrypt the payload
The frontend question nobody asks early enough
If JWE is encrypted… how does the frontend use it?
Short answer:
It doesn't read it.
Typical flow:
- Backend creates the JWE
- Frontend stores it (memory / cookie / storage)
- Frontend sends it back on requests
- Backend decrypts it
The frontend treats it as an opaque blob.
Why the frontend should not decrypt JWE
Decryption requires a private key.
If that key exists in frontend code:
- It can be extracted
- The encryption becomes meaningless
Browsers are not secure environments:
- extensions
- dev tools
- network proxies
Everything shipped to the client can be inspected.
Where I keep seeing this go wrong
The pattern repeats:
Teams adopt signed JWTs… then start putting sensitive data inside:
- emails
- internal IDs
- roles
- permissions
Because it "looks secure".
It isn't.
Every system touching that token can read it:
- browser storage
- logs
- middleware
- proxies
In fintech, that's not just bad design — it becomes a GDPR / PSD2 issue.
The rule I stick to
If the data needs to stay secret, it doesn't go in a signed JWT.
Either:
- use JWE (decrypt server-side only)
- or don't put it in the token at all
Quick mental model
- JWT → format
- JWS → trust the data hasn't changed
- JWE → hide the data
Final thought
JWT is a good tool. I use it daily.
But:
encoded ≠ encrypted signed ≠ secret
Treating a transparent envelope like a vault is how sensitive data ends up where it shouldn't be.
Written by The Fintech Engineer Breaking down how money really works in the modern world.