JWT Explained for Beginners — With Simple Math Analogies
Source: Dev.to
Introduction
When a user logs in, the server needs to remember who they are on every request. Traditional sessions store data on the server, while a JWT (JSON Web Token) packs the user information—such as user ID, roles, and expiry—directly into the token. The server then only verifies the signature on each request, avoiding a database lookup.
JWT Structure
A JWT consists of three parts joined by dots:
header.payload.signature
Header
The header specifies the signing algorithm (e.g., HS256 or RS256) and the token type.
Payload
The payload contains the actual user data, called claims. Common claims include:
sub→ Subject (user ID)iss→ Issueraud→ Audienceexp→ Expiration timeiat→ Issued at
Signature
The signature ensures the token’s integrity. To create it, the server:
- Base64‑encodes the header and payload.
- Joins them with a dot (
.) to form the message. - Applies a hashing function together with a secret key (or private key) to produce the signature.
The signature is then appended to the token.
Token Verification
1. HS256 (symmetric)
Both token generation and verification use the same secret key.
Analogy:
- Secret = 3
- Signing rule = multiplication by the secret
Token generation
message = 10
signature = message * secret # 10 * 3 = 30
token = 10.30
Token validation
received_token = 10.30
recalculated_signature = 10 * 3 # 30
recalculated_signature == 30 # → valid
If an attacker modifies the message:
received_token = 18.30
recalculated_signature = 18 * 3 # 36
recalculated_signature == 30 # → invalid
2. RS256 (asymmetric)
The server signs with a private key; verification uses a public key. This allows multiple services to verify tokens without sharing the private key.
Simplified analogy (not real RSA):
Private key operation = multiply by 3
Public key operation = divide by 3
Signing (token generation)
message = 10
signature = message * 3 # 30
token = 10.30
Verification
received_token = 10.30
expected_message = signature / 3 # 30 / 3 = 10
expected_message == 10 # → valid
Modified message
received_token = 20.30
expected_message = 30 / 3 # 10
expected_message == 20 # → invalid
Wrong public key
public_key = divide by 5
expected_message = 30 / 5 # 6
expected_message == 10 # → invalid
Important Security Note
The payload is only Base64‑encoded, not encrypted. Anyone can decode and read its contents. Therefore, never store sensitive data (e.g., passwords) inside a JWT. The signature guarantees that the token has not been tampered with, but it does not hide the data.