AI Overview SummaryJWTs have well-known architectural vulnerabilities. Learn how PASETO corrects these design flaws through strict versioning, cipher suites, and cryptographic boundaries.
The Ubiquity and Vulnerability of JSON Web Tokens
For years, JSON Web Tokens (JWT) have been the industry standard for state-less authentication in modern API-driven architectures. Designed by the IETF in RFC 7519, JWTs allowed services to exchange digitally signed claims (such as user identities, roles, and scope permissions) securely without consulting a central session database.
However, the flexible, multi-standard design of the JSON Web Signature (JWS) and JSON Web Encryption (JWE) specifications introduced a wide array of vulnerabilities. By allowing developers—and worse, clients—to choose the cryptographic algorithms and parameters dynamically via the token header, JWT created a legacy of security vulnerabilities. Common exploits, such as the infamous "alg": "none" bypass and key-confusion attacks, have repeatedly exposed production APIs to unauthorized access.
To address these core design flaws, cryptographic security experts created PASETO (Platform-Agnostic Security Tokens). PASETO eliminates algorithm negotiation, enforces strict versioning, and provides secure-by-default token implementations.
In this deep dive, we will explore the structural flaws of JWT, analyze how PASETO corrects these errors, compare the local (symmetric) and public (asymmetric) security profiles of PASETO, and outline migration strategies for modern web projects.
1. The Design Flaws of JWT
JWT's primary vulnerability is its algorithm agility. Algorithm agility allows a single parser to support a wide range of cryptographic algorithms and options, relying on metadata inside the payload header to determine how to process the token.
A. The "alg": "none" Bypass
A JWT is composed of three parts separated by periods: Header.Payload.Signature. The header is a base64-encoded JSON block that tells the library how to verify the signature:
{
"alg": "HS256",
"typ": "JWT"
}
The JWT standard supports the "none" algorithm, intended for debugging or internal system communication where signing is unnecessary. However, if a developer uses a library that doesn't explicitly restrict "none", an attacker can modify a valid admin token, change the header's "alg" property to "none", strip the signature block, and send the modified token:
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiJhZG1pbiJ9.
Many early JWT libraries would automatically accept this token as valid because the header instructed them to perform no signature verification.
B. HMAC vs. RSA Key Confusion (RS256 to HS256)
Key-confusion attacks occur when a backend uses asymmetric cryptography (RS256) to verify tokens but uses a library that accepts symmetric keys (HS256) under the same verification function.
- RS256 (Asymmetric): The auth server signs the token with a private key, and resource servers verify the signature using a public key. The public key is widely distributed.
- HS256 (Symmetric): The token is signed and verified using the same secret key.
If the resource server's verification library accepts the algorithm parameter dynamically from the token's header, an attacker can:
- Retrieve the resource server's public key (which is public).
- Create a modified token containing the desired admin claims.
- Change the header to
"alg": "HS256". - Sign the token using the public key as if it were an HMAC shared secret.
When the verification library reads the header, it sees "HS256". It looks for the verification key, finds the configured public key, uses it to perform a symmetric HMAC-SHA256 signature check, and declares the token valid. The token is verified successfully because the attacker signed it with the exact key the library used for validation.
2. Enter PASETO: Secure by Design
PASETO rejects algorithm agility in favor of cryptographic versioning. Instead of relying on a header that defines individual algorithms, PASETO defines strict, immutable versions. Each version specifies a fixed cipher suite (combination of algorithms) that cannot be altered or negotiated by the client.
paseto.Version.Purpose.Payload.Footer
The Structure of a PASETO Token
A PASETO token consists of four dot-separated parts:
- Protocol Version: (e.g.,
v2,v4). - Purpose: The type of token:
local: Symmetric encryption (shared secret).public: Asymmetric digital signatures (public/private keys).
- Payload: The encrypted or signed claims.
- Footer: (Optional) Public metadata or key identifiers.
The Cipher Suites
Each version maps to a strict suite:
- Version 4 (Modern/Recommended):
local: Symmetric encryption using AES-256-CTR combined with HMAC-SHA384 (Encrypt-then-MAC paradigm) or ChaCha20-Poly1305.public: Asymmetric signatures using Ed25519 (Edwards-curve Digital Signature Algorithm).
- Version 2 (Legacy/Compatibility):
local: AES-256-GCM authenticated encryption.public: Asymmetric signatures using Ed25519.
If an attacker tries to change the payload or header, there is no algorithm metadata field to manipulate. The validation library expects a specific version (e.g., v4.public) and will only run Ed25519 signature verification. Any attempt to pass a symmetric token or a different algorithm signature will fail immediately.
3. Comparing Token Structures
JWT Layout:
[Header (alg/typ)] . [Claims (sub/exp/roles)] . [Signature]
Note: The claims are plain text (Base64-encoded). Anyone who intercepts a signed JWT can read the payload contents.
PASETO Layout:
-
Symmetric (
v4.local):v4.local.[Encrypted Payload]The payload is fully encrypted. Even if intercepted, the claims are unreadable without the secret key.
-
Asymmetric (
v4.public):v4.public.[Claims (Base64)] . [Ed25519 Signature]The claims are readable but protected by Ed25519 signatures, which are mathematically immune to the key-confusion exploits that affect RSA-based systems.
4. Architectural Comparison: JWT vs. PASETO
| Feature | JWT (RFC 7519) | PASETO | | :--- | :--- | :--- | | Algorithm Agility | Yes (Dynamic negotiation via header) | No (Strict cryptographic versioning) | | Payload Privacy | Signed tokens are cleartext (JWS) | Local tokens are encrypted by default | | Signature Algorithm| RSA, ECDSA, HMAC, none | Ed25519 (EdDSA) | | Key Confusion Risk | High | None (strict separation of local/public) | | Cryptographic Standard| Complex, error-prone (JOSE suite) | Simplified, modern primitives |
5. Implementing PASETO in Node.js
Below is an implementation of token creation and validation using the popular paseto library in Node.js, demonstrating asymmetric digital signatures (public purpose):
Installation:
npm install paseto
Key Generation and Token Sign/Verify Code:
const { V4 } = require('paseto');
const crypto = require('crypto');
// Generate an Ed25519 private/public keypair
const { publicKey, privateKey } = crypto.generateKeyPairSync('ed25519');
/**
* Signs a payload using Ed25519 asymmetric signatures (v4.public)
* @param {object} claims - User authorization claims
* @returns {Promise<string>} The signed PASETO token
*/
async function generateAccessToken(claims) {
const token = await V4.sign(claims, privateKey, {
expiresIn: '2h',
audience: 'https://api.myutilitybox.com',
issuer: 'auth.myutilitybox.com'
});
return token;
}
/**
* Verifies a PASETO token using the corresponding public key
* @param {string} token - The raw PASETO token
* @returns {Promise<object>} The validated payload claims
*/
async function verifyAccessToken(token) {
try {
const payload = await V4.verify(token, publicKey, {
audience: 'https://api.myutilitybox.com',
issuer: 'auth.myutilitybox.com'
});
return payload;
} catch (err) {
throw new Error('Token verification failed: ' + err.message);
}
}
// Demo Execution
(async () => {
const claims = { userId: 'usr_998273', role: 'administrator' };
const token = await generateAccessToken(claims);
console.log("Generated Token:", token);
// Output format: v4.public.ey...
const verified = await verifyAccessToken(token);
console.log("Verified Claims:", verified);
})();
Conclusion
While JSON Web Tokens remain standard across legacy enterprise environments, they introduce significant security risks due to algorithm negotiation. For modern API platforms, greenfield projects, and microservices where developer productivity and robust default security are critical, PASETO is a superior alternative. By enforcing strict cipher suites and making key-confusion exploits mathematically impossible, PASETO reduces the security surface area of web authentication.
Ready to use the engine?
Deploy our high-precision Dev Tools manifest for your professional workload. Fast, free, and privacy-encrypted.
Launch Why Tool