Engineering ThoughtApril 2026
#LearnSecurity: PASETO vs JWT
Alternative to JWT, Sessions, Cookies, OAuth — Exploring PASETO with practical examples and RFC specs.

// PASETO Token Security
Authentication is one of those things every backend developer has to deal with. We've all been there — staring at the screen wondering whether to use Sessions, JWT, or maybe just roll our own (please don't).
Recently I stumbled into PASETO (Platform-Agnostic Security Tokens) while reading through some RFC drafts. It's been around for a few years but still flies under the radar for many developers. Let me break down what I learned.
###🔐 What Problem Are We Solving?
Before PASETO, we had a few options for stateless auth:
PASETO sits in the same space as JWT — stateless, self-contained tokens — but tries to fix the footguns.
###📝 JWT vs PASETO: The Payload Difference
Here's where it gets interesting. Let's look at a real payload comparison.
JWT (JSON Web Token):
snippet.json
The full JWT looks like:
snippet.text
Problems I see:
1. That payload is just Base64 — paste it into jwt.io and anyone can read it
2. The
alg header can be tampered with (famous alg: none attack)
3. I have to choose the algorithm — HS256? RS256? ES256?PASETO (Platform-Agnostic Security Token):
PASETO has two modes: local (encrypted) and public (signed).
PASETO Local Mode (v4):
snippet.text
What's inside? Encrypted. You can't read it without the shared secret. The structure is:
snippet.text
v4= Version 4 (uses XChaCha20-Poly1305 for encryption)local= Symmetric encryption modepayload= Encrypted claimsfooter(optional) = Unencrypted metadata (like key ID)
PASETO Public Mode (v4):
snippet.text
public= Signed with Ed25519 (asymmetric)- Anyone can verify with the public key
- Only the private key holder can create valid tokens
###🛡️ Why I Started Paying Attention
1. No Algorithm Confusion
JWT's algorithm is in the header. Change
HS256 to none and some broken implementations accept it. PASETO bakes the algorithm into the version — you can't change it.2. Encrypted by Default (Local Mode)
With JWT, the payload is public. With PASETO local mode, it's encrypted. If I'm passing internal user IDs or permissions, I'd rather they weren't visible to anyone who intercepts the token.
3. Simple Choices
JWT: "Pick your algorithm, pick your key size, configure it right"
PASETO: "Pick local or public. Done."
###💻 Practical Example
Here's how you'd actually use PASETO in Node.js/Bun:
snippet.ts
Compare to JWT:
snippet.ts
###📚 The Spec
PASETO isn't just a library — it's a specification. The RFC (currently in draft) defines:
- v1: NIST-compliant algorithms (RSA-PSS, AES-256-CTR, HMAC-SHA384)
- v2: libsodium-based (Ed25519, XChaCha20-Poly1305)
- v3: NIST PQC-ready algorithms
- v4: Modern libsodium (Ed25519, XChaCha20-Poly1305) — recommended
Reference: paseto-standard/paseto-spec
###🚀 My Implementations
I built two boilerplates to experiment with PASETO in real projects:
Bun + Elysia.js + PASETO
github.com/aldoignatachandra/Bun-Elysiajs-Paseto-Boilerplate
A minimal REST API with PASETO local mode. Good starting point if you want to see auth middleware, token refresh, and protected routes working together.
Bun + Hono + PASETO + GraphQL
github.com/aldoignatachandra/Bun-Hono-Paseto-GraphQL
Same idea but with GraphQL. Shows how to handle authentication in a GraphQL context using PASETO for context/authorization.
Both use PASETO v4 and demonstrate the "local" mode for encrypted session tokens.
###🤔 When to Use What?
###🌟 Bottom Line
JWT isn't going anywhere. The ecosystem is huge and it works fine if you're careful. But PASETO removes entire categories of mistakes — algorithm confusion, weak crypto choices, accidentally exposing payload data.
For new projects where I control the whole stack? I'm reaching for PASETO. The peace of mind is worth the smaller ecosystem.
For existing JWT implementations? Probably not worth refactoring unless you're already touching auth code.
Got questions or want to see more backend patterns? I post experiments and boilerplate project for learn on GitHub.
Happy Coding!