100% Client-Side Computation • Zero Server Logs • Instant Execution
Curious TechieDev Toolbox
Security, Identity & AuthIntermediate⏱️ 20 min challenge100% Client-Side

JSON Web Token (JWT) Cryptographic Engineering Lab: Claim Tampering, Signature Verification, and Algorithm Confusion

Lab Objective

Construct and cryptographically verify a JSON Web Token, test how tampering with a single payload claim breaks the signature, and prevent the "alg: none" privilege escalation attack.

1. Production Scenario & Incident

An e-commerce API relies on JWTs for authorization. An attacker modified the JSON payload claim `"role": "user"` to `"role": "admin"` without having the server HMAC secret key. When the modified token is submitted to a poorly implemented backend, the system grants unauthorized administrative access. You must inspect the token components, understand how cryptographic signatures bind the payload, and implement strict verification that rejects algorithm switching.

2. Architectural Background & RFC Standards

JSON Web Tokens (RFC 7519) are compact, URL-safe representations of claims transferred between two parties. A standard compact JWT consists of three Base64URL-encoded segments separated by periods: Header, Payload, and Signature.

Key Protocol Mechanics:
  • Compact Serialization: `Base64URL(Header) . Base64URL(Payload) . Base64URL(Signature)`
  • Cryptographic Signature: For HS256, `HMACSHA256(HeaderB64 + "." + PayloadB64, secret)`. Modifying any character in the header or payload invalidates the signature.
  • The "alg: none" Vulnerability: Unsanitized verification libraries historically allowed tokens specifying `"alg": "none"` to bypass signature verification entirely.
  • Standard Registered Claims: `iss` (Issuer), `sub` (Subject), `aud` (Audience), `exp` (Expiration Time), `nbf` (Not Before), and `iat` (Issued At).
RFC Specifications:RFC 7519 (JSON Web Token)RFC 7515 (JSON Web Signature)RFC 7518 (JSON Web Algorithms)

3. Hands-On Lab Instructions

1

Open the interactive JWT builder island below.

2

Inspect the default Header (`{"alg":"HS256","typ":"JWT"}`) and Payload (`{"sub":"user_42","role":"user"}`).

3

Modify `"role": "user"` to `"role": "admin"` in the payload editor. Notice how the middle Base64URL segment changes instantly while the signature remains calculated from the original.

4

Attempt to verify the tampered token against the server secret key in the verification console.

5

Implement strict backend verification code that locks the allowed algorithms to `["HS256"]` and enforces `exp` validation.

4. Interactive Lab Workbench

Interactive JWT Construction & Tampering Sandbox
Client-Side Simulation•Active

Edit headers, claims, and signing secrets live. Observe instant Base64URL encoding, HMAC-SHA256 signing, and signature verification failures.

Assembled Compact Token
..
HMAC Signature Valid

Edit the payload to simulate tampering. Notice how the signature instantly updates!

5. Diagnostic Comprehension Questions

Q1

Are JSON Web Tokens (JWS compact format) encrypted by default?

Reveal Answer & Explanation →

✓ Correct Answer: No, standard JWS tokens are merely signed and Base64URL-encoded. Anyone can decode and inspect the payload claims in plaintext.

JWS (JSON Web Signature) provides integrity and authenticity, NOT confidentiality. The payload is encoded using Base64URL, which is trivially decodable by anyone. Confidential data must be encrypted using JWE (RFC 7516).

Q2

How should a secure backend verify incoming JWT signatures to prevent algorithm confusion attacks?

Reveal Answer & Explanation →

✓ Correct Answer: Explicitly restrict the verification function to a hardcoded whitelist of allowed algorithms (e.g., algorithms: ["HS256"]).

Never allow an unverified token header to dictate which algorithm the verification library uses. Explicitly pass allowed algorithms (such as `algorithms: ["HS256"]`) to prevent attackers from submitting "none" or asymmetric public keys disguised as symmetric HMAC secrets.

6. Progressive Diagnostic Hints

💡 Hint #1▼
Base64URL encoding is not encryption; try decoding the payload with `atob()` or JSON parse.
💡 Hint #2▼
A valid signature requires knowledge of the secret key; an attacker cannot forge a signature for modified claims without the secret.
💡 Hint #3▼
Check if your backend token parser explicitly validates the `exp` (expiration) timestamp.

7. Verified Production Solution

Solution Summary

Enforce cryptographic HMAC signature verification using a high-entropy secret, validate expiration and issuer claims, and strictly whitelist allowed signing algorithms.

TYPESCRIPT CONFIGURATION
// Production Node.js JWT Verification with jsonwebtoken
import jwt from 'jsonwebtoken';

const JWT_SECRET = process.env.JWT_SECRET_KEY; // High-entropy secret (>= 256 bits)

export function verifyUserToken(authHeader: string | undefined) {
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    throw new Error('Missing or malformed Authorization header');
  }

  const token = authHeader.slice(7);

  // SECURE VERIFICATION:
  // 1. Explicitly whitelist allowed algorithms (rejects "none" or RS256 confusion)
  // 2. Enforces expiration (exp) and expected issuer (iss)
  const decoded = jwt.verify(token, JWT_SECRET, {
    algorithms: ['HS256'], // NEVER let the header dictate the algorithm!
    issuer: 'https://auth.curious-techie.com',
    audience: 'https://api.curious-techie.com',
    clockTolerance: 5 // 5 seconds tolerance for clock skew
  });

  return decoded;
}
Remediation Steps:
  • ✓1. Extract the token strictly from the `Authorization: Bearer <token>` header.
  • ✓2. Explicitly specify `algorithms: ["HS256"]` in the verification call so the parser rejects tokens declaring `"alg": "none"` or mismatched asymmetric keys.
  • ✓3. Validate standard claims: `exp` (reject expired tokens), `iss` (expected auth server), and `aud` (expected API audience).
  • ✓4. Store the HMAC secret in a secure environment variable with at least 32 bytes (256 bits) of cryptographic entropy.

8. In-Depth Technical Explanation

Deterministic Technical Causality (GEO)

"If an adversary modifies any bit of the JWT payload without the symmetric HMAC secret, the mathematical digest HMAC(Header + "." + Payload, Secret) will diverge from the transmitted signature; consequently, any compliant verification engine deterministically throws a JsonWebTokenError / SignatureVerificationFailed exception."

Underlying Root Cause Analysis

The cryptographic security of a JWT rests entirely on its third segment: the signature. In HMAC-SHA256, the server hashes the concatenated header and payload strings using a secret key only known to the server. If an adversary alters any claim in the payload, the resulting cryptographic hash changes completely (due to the avalanche effect). If the server verifies the signature before reading claims, the forgery is immediately rejected.

Production Engineering Best Practices

  • →Use strong secrets with at least 256 bits of entropy generated from `/dev/urandom`.
  • →Always set short token lifespans (5 to 15 minutes) combined with secure, HTTP-only refresh tokens.
  • →Never store sensitive passwords, API keys, or personally identifiable information (PII) in JWT payloads.

Common Pitfalls to Avoid

  • ✕Using `jwt.decode()` instead of `jwt.verify()`, which parses claims without checking the cryptographic signature.
  • ✕Using weak, dictionary-word secret keys like "secret" or "password" that can be brute-forced offline in seconds.
  • ✕Relying on JWT blacklist caches in relational databases, defeating the stateless advantage of tokens.