JWT vs PASETO vs Session-Based Auth

Table of contents
- The Token Confusion is Real
- What Are These Token Systems Anyway?
- Deep Comparison: JWT vs PASETO vs Session
- Token System Comparison Flow
- Security Tradeoffs You Should Know
- When to Use Each System
- Sample: PASETO Token in Node.js (v2.local)
- Don’t Forget Storage Strategy
- Advanced Patterns: Combine the Best of All Worlds
- Conclusion: No Silver Bullet, Only Smart Tradeoffs
- Call to Action

Are JWTs safe?
Should you switch to PASETO?
Is session-based auth outdated?
In this guide, we’ll compare modern token systems in depth with use cases, vulnerabilities, and practical advice.
The Token Confusion is Real
Developers are spoiled with options: JWT, PASETO, session-based auth, opaque tokens…
But wrong choices lead to real security issues: replay attacks, token leaks, poor scaling.
This post cuts through the noise:
What each system offers
Common myths (like “JWT is always better”)
When to use what with code and examples
What Are These Token Systems Anyway?
JSON Web Token (JWT)
Self-contained, signed token (JWS or JWE)
Carries user identity + claims (e.g.
sub
,exp
,role
)No server-side session store needed
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
PASETO (Platform-Agnostic Security Token)
Like JWT, but designed to be safer by default
Eliminates common JWT footguns:
No
none
algorithmStrong encryption (local/public mode)
v2.local.AAAAAAAAAA... (encrypted)
Session-Based Authentication
Server issues a session ID, stores session in memory/Redis
Client stores session ID in a secure HttpOnly cookie
Stateless = ❌ (server must track sessions)
Super common with Rails, Django, Express
Deep Comparison: JWT vs PASETO vs Session
Feature | JWT | PASETO | Session-Based |
Stateless | ✅ | ✅ | ❌ |
Scalable | ✅ | ✅ | ⚠️ Needs Redis |
Tamper-proof | ✅ (signed) | ✅ (signed/encrypted) | ✅ |
Encrypted by default | ❌ (JWS not encrypted) | ✅ (v2.local) | ✅ |
Revocation | ❌ (needs hacks) | ❌ (same) | ✅ Easy |
Susceptible to replay | ✅ if not fingerprinted | ✅ if not fingerprinted | ❌ (tied to cookie/session store) |
Complexity | Medium | High | Low |
Security footguns | Several | Few | Few |
Storage method | Header/localStorage | Header | Secure cookie |
Token System Comparison Flow
graph TD
subgraph JWT
A1[Client Logs In] --> A2[Server Issues JWT]
A2 --> A3[Client Stores JWT]
A3 --> A4[Client Sends JWT on Each Request]
A4 --> A5[Server Verifies Signature]
A5 --> A6[Access Granted if Valid]
end
subgraph PASETO
B1[Client Logs In] --> B2[Server Issues Encrypted PASETO]
B2 --> B3[Client Stores PASETO]
B3 --> B4[Client Sends PASETO on Each Request]
B4 --> B5[Server Decrypts and Verifies]
B5 --> B6[Access Granted if Valid]
end
subgraph Session
C1[Client Logs In] --> C2[Server Creates Session + ID]
C2 --> C3[Session ID Stored in Server/Redis]
C3 --> C4[Client Gets HttpOnly Cookie]
C4 --> C5[Client Sends Cookie on Each Request]
C5 --> C6[Server Looks Up Session ID]
C6 --> C7[Access Granted if Session Valid]
end
What This Shows?
Model | Validation Location | Revocation Possible? | Token Storage |
JWT | Verified by signature | ❌ No (unless using blacklist) | Header / localStorage |
PASETO | Decrypted + verified | ❌ No (same) | Header / localStorage |
Session | Validated server-side | ✅ Yes | HttpOnly Secure Cookie |
Security Tradeoffs You Should Know
🚨 JWT Pitfalls
No built-in revocation - token lives until expiry
Stored in
localStorage
? Risk of XSS token theftExposed to replay attacks if not bound to IP/device
🔐 PASETO Advantages
Better defaults (e.g., encrypted-by-default in
v2.local
)Safer crypto choices (no
none
, avoids RS/HS confusion)Libraries exist for Node, Go, Python, Rust
🛡️ Session-Based Auth Pros
Safe with secure HttpOnly cookies
Easy to revoke
Better suited for traditional web apps with CSRF protection
When to Use Each System
Use Case | Recommendation |
Public REST APIs with scaling needs | JWT or PASETO with short-lived tokens |
Mobile apps / device auth | JWT/PASETO with refresh + fingerprint binding |
Enterprise dashboards or internal portals | Session-based auth (fast, revocable) |
High-risk environments | PASETO + rotated tokens + IP/device binding |
Multi-device auth | Session-based or fingerprint-aware JWT |
Sample: PASETO Token in Node.js (v2.local)
npm install paseto
const { V2 } = require('paseto');
const key = await V2.generateKey('local');
const token = await V2.encrypt(
{ sub: 'user123', role: 'admin' },
key
);
// Later, verify:
const payload = await V2.decrypt(token, key);
PASETO automatically encrypts everything. You don’t need to worry about alg
, exp
, or iat
footguns like in JWTs.
Don’t Forget Storage Strategy
Method | Safe? | Notes |
localStorage | ❌ | Vulnerable to XSS |
sessionStorage | ⚠️ | Limited scope, still XSS-prone |
HttpOnly Secure Cookies | ✅ | Best for session or refresh token storage |
Advanced Patterns: Combine the Best of All Worlds
Access token + refresh token model (JWT/PASETO short-lived + session-like refresh)
Use fingerprinting (IP, User-Agent, device ID) for sensitive actions
OPA or RBAC rules to enforce access control server-side
Conclusion: No Silver Bullet, Only Smart Tradeoffs
There’s no one-size-fits-all token. Your choice should depend on:
Threat model (XSS? Replay? Insider access?)
Scaling needs (server-side sessions or stateless?)
App architecture (SPA vs server-rendered vs mobile)
Choose wisely and always treat token security as part of system design, not just implementation detail.
Call to Action
Which system are you using and why? Have you tried PASETO or are you still on JWTs?
Let’s break it down in the comments 👇
Subscribe to my newsletter
Read articles from Faiz Ahmed Farooqui directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Faiz Ahmed Farooqui
Faiz Ahmed Farooqui
Principal Technical Consultant at GeekyAnts. Bootstrapping our own Data Centre services. I lead the development and management of innovative software products and frameworks at GeekyAnts, leveraging a wide range of technologies including OpenStack, Postgres, MySQL, GraphQL, Docker, Redis, API Gateway, Dapr, NodeJS, NextJS, and Laravel (PHP). With over 9 years of hands-on experience, I specialize in agile software development, CI/CD implementation, security, scaling, design, architecture, and cloud infrastructure. My expertise extends to Metal as a Service (MaaS), Unattended OS Installation, OpenStack Cloud, Data Centre Automation & Management, and proficiency in utilizing tools like OpenNebula, Firecracker, FirecrackerContainerD, Qemu, and OpenVSwitch. I guide and mentor a team of engineers, ensuring we meet our goals while fostering strong relationships with internal and external stakeholders. I contribute to various open-source projects on GitHub and share industry and technology insights on my blog at blog.faizahmed.in. I hold an Engineer's Degree in Computer Science and Engineering from Raj Kumar Goel Engineering College and have multiple relevant certifications showcased on my LinkedIn skill badges.