Lesson 21. Why PASETO is better than JWT for token-based authentication?

Token-based authentication is a cornerstone of modern web development. For years, the go-to standard has been the JSON Web Token (JWT). However, JWT’s design, which offers developers a vast array of configuration options and algorithms, has proven to be its greatest weakness. This flexibility has led to numerous critical security vulnerabilities in real-world applications.

A newer alternative, PASETO (Platform-Agnostic Security Tokens), solves many of JWT’s problems by enforcing stronger cryptography and simplifying usage.

In this lesson, we’ll learn:

  • How token-based authentication works.
  • JWT’s structure and weaknesses.
  • How PASETO improves security and usability.

1. How Token-Based Authentication Works

  1. The client logs in by sending a username and password.
  2. The server verifies the credentials.
  3. If valid, the server generates a signed access token and returns it.
  4. The client uses this token to access protected resources (e.g., GET /accounts).
  5. The server verifies the token’s validity before authorizing the request.

Tokens usually have an expiration time, after which the client must log in again.

Key Benefits of Token-Based Authentication

Stateless Authentication:

  • Server doesn’t need to store session state
  • Tokens contain all necessary information
  • Scalable across multiple server instances

Understanding JWT Structure

A JWT is a string with three base64-encoded parts, separated by dots (.):
HEADER.PAYLOAD.SIGNATURE

  • Header: Contains metadata, most importantly the signing algorithm (alg), e.g., {"alg": "HS256", "typ": "JWT"}.
  • Payload: Contains the actual “claims” (user data, expiration, etc.), e.g., {"user": "alice", "exp": 1633340400}This data is only encoded, not encrypted.
  • Signature: A cryptographic signature created by signing the HEADER.PAYLOAD combination with a secret or private key.
Understanding JWT Structure

JWT Algorithm Categories

Symmetric Key Algorithms (Local Use)

The first one is symmetric-key algorithm is fast and efficient, where the same secret key is used to both sign and verify the tokens. And since there’s only 1 key, it should be kept secret, So this algorithm is suitable for local use only, or in other words, for internal services, where the secret key can be shared. However, we cannot use it in case there’s an external third party service that wants to verify the token, because it would mean we must give them our secret key.

HMAC-based algorithms:

  • HS256: HMAC with SHA-256
  • HS384: HMAC with SHA-384
  • HS512: HMAC with SHA-512

Asymmetric Key Algorithms (Public Use)

In this type of algorithm, there’s a pair of keys instead of just 1 single secret key. The private key is used to sign the token, while the public key is used only to verify it.

Therefore, we can easily share our public key with any external third party services without worrying about leaking our private key. Within this asymmetric-key category, there are several group of algorithms,

RSA-based algorithms:

  • RS256: RSA with PKCS#1 v1.5 and SHA-256
  • PS256: RSA with PSS and SHA-256 (more secure)

ECDSA-based algorithms:

  • ES256: ECDSA with P-256 curve and SHA-256

Characteristics:

  • Private key for signing, public key for verification
  • Can share public key with third parties
  • More computationally expensive
  • Suitable for distributed systems

Section 2: Problems with JWT

Despite its popularity, JWT suffers from serious design flaws:

1. Weak algorithm choices

  • Developer had Too Many Algorithm Choices: JWT supports dozens of algorithms, including known vulnerable ones (e.g., RS256 with PKCSv1.5 is susceptible to padding oracle attacks). This “choice” is a foot-gun for developers who are not cryptography experts.
  • Example: RSA with PKCSv1.5 (vulnerable to padding oracle attacks).

Algorithm confusion attacks

  • The alg header can be manipulated.
  • Example: An attacker changes the algorithm to HS256 and signs with the server’s public key, tricking the server into validating a forged token.

2. The “none” Algorithm Attack

Vulnerable JWT Header: Early libraries allowed alg: none, meaning no signature check at all. This made token forgery trivial.

{
  "alg": "none",
  "typ": "JWT"
}
  • How it works: An attacker modifies the token header to {"alg": "none"} and strips the signature. A poorly implemented JWT library might see this and skip signature verification entirely, accepting any token.
  • Status: Well-known and mostly fixed in modern libraries, but a classic example of JWT’s problematic design.

Attack Vector:

  1. Attacker creates malicious payload
  2. Sets algorithm to “none”
  3. Removes signature entirely
  4. Server accepts unsigned token if not properly validated

3. Asymmetric to Symmetric Confusion

A more dangerous attack happens when the algorithm in the header is changed to a symmetric one (like HS256), even though the server actually uses an asymmetric algorithm (like RSA).

Here’s why this works: the server’s RSA public key is public. A hacker can take that key, create a fake token for an admin user, and set the header algorithm to HS256. Since HS256 is symmetric, the server may mistakenly use the public key as a shared secret, allowing the fake token to pass verification.

Weak Algorithm Choices

Vulnerable Algorithms in JWT Standard:

3. Implementation Pitfalls

// ❌ BAD: No algorithm validation
token, err := jwt.Parse(tokenString, keyFunc)

// ❌ BAD: Accepting any algorithm
if token.Method.Alg() != "" { // Wrong check
    return keyFunc(token)
}

// ✅ GOOD: Strict algorithm validation
if token.Method.Alg() != "RS256" {
    return nil, errors.New("invalid algorithm")

OK, so now you know why JSON web token is not a very well-designed standard. It opens the door to many potential threats, Therefore, many people are trying to stay away from it, and migrate to something more robust.

PASETO, or Platform Agnostic Security Token is one of the most successful design that are being widely accepted by the community as the best secured alternative to JWT.


PASETO: The Superior Alternative and solved these problems

PASETO’s philosophy is to eliminate dangerous choices. PASETO actually encrypts and authenticates all data in the token with a secret key, using a strong Authenticated Encryption with Associated Data (or AEAD) algorithm. It provides a secure default for each use case. PASETO design principle as follows.

1. Secure by Default

  • No algorithm choice for developers
  • Only proven, secure algorithms included
  • Eliminates algorithm confusion attacks
  • No alg header
  • Authenticated Encryption (AEAD) for local tokens

PASETO Versions and Algorithms

  • Version 1 (legacy use)
    • The AEAD algorithm used in PASETO version 1 is AES256 CTR with HMAC SHA384.
    • Symmetric: AES256-CTR + HMAC-SHA384
    • Asymmetric: RSA-PSS + SHA384, For public cases, where there are external services that needs to verify the token, we have to use asymmetric-key algorithm. In that case, PASETO uses the same approach as JWT, which means, it doesn’t encrypt the token data. For legacy systems (AES-256-CTR + HMAC-SHA384 for local, RSA-PSS for public).
  • Version 2 (recommended)
    • In the latest version of PASETO, version 2, 2 more secured and modern algorithms are being used.
    • For local symmetric-key scenario, it uses XChaCha20 + Poly1305 (AEAD)
    • Asymmetric: Ed25519 (digital signatures). Uses modern cryptography (XChaCha20-Poly1305 AEAD for local, Ed25519 elliptic curves for public). Benefits: Fast, secure, resistance to side-channel attacks

At most two versions are active at the same time, simplifying adoption and avoiding weak choice. Because the algorithm header doesn’t exist anymore, So the attacker cannot set it to “none” or force the server to use the algorithm it chose in this header.
Everything in the token is also authenticated with AEAD, so it’s not possible to tamper with.

PASETO Token Structure

Local Token (symmetric, encrypted)

4 parts:

  1. Version (v2)
  2. Purpose (local)
  3. Payload (encrypted)
  4. Footer (optional, base64-encoded metadata)

The encrypted payload contains:

  • Body (claims + expiration)
  • Nonce
  • Authentication tag

Decrypted Payload:

{
  "username": "john_doe",
  "exp": "2023-10-15T10:30:00Z",
  "iat": "2023-10-15T08:30:00Z"
}

Public Token (asymmetric, signed only)

3 parts:

  1. Version (v2)
  2. Purpose (public)
  3. Payload (base64 encoded, includes JSON body + signature)

Why PASETO is Better

  • No weak algorithm choices → strong defaults only.
  • No alg header → prevents trivial forgery.
  • Encryption for local tokens → payload confidentiality.
  • Simpler implementation → fewer chances for developer mistakes.
  • Modern cryptography → comparable to TLS 1.3 design philosophy.

Security Comparison: JWT vs PASETO

Security Comparison: JWT vs PASETO

Conclusion

JWT’s design flaws have led to many real-world vulnerabilities.
PASETO was created to solve these issues with:

  • Strong algorithms by default.
  • Encryption for local tokens.
  • Simpler, safer usage.
Scroll to Top