REST API with Express.js
Structure of a Web Token (JWT)

JSON Web Tokens (JWT) are a compact and self-contained way to securely transmit information between parties as a JSON object. A typical JWT consists of three parts, separated by dots:

HEADER.PAYLOAD.SIGNATURE

Example of a full JWT:


eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJ1c2VybmFtZSI6Im1haWphMTIzIiwiZXhwIjoxNzE4MTE4MDAwfQ.
SGp1Y2la3EXAMPLE2wR7J_yPaAogwEXAMPLEqj8c
  
1. Header

The header typically consists of two fields:

{
  "alg": "HS256",
  "typ": "JWT"
}
  • alg: The signing algorithm, e.g., HS256.
  • typ: The token type, always "JWT".
2. Payload

The payload contains the actual data (claims). These can be custom claims or registered ones:

{
  "username": "teppotesti",
  "exp": 1718111800,
  "iat": 1718110000
}
  • username: Custom data related to the user.
  • exp: Expiration time (as a UNIX timestamp).
  • iat: Issued-at time.

Note: The payload is not encrypted, so it's visible to anyone who has the token. However, it cannot be modified without invalidating the signature.

3. Signature

The signature ensures the token's integrity. It's created using the header and payload, combined with a secret key:

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

This makes it possible to verify that the token hasn't been tampered with.

Summary

JWTs are useful for stateless authentication. The payload carries identity and metadata, and the signature ensures the token's authenticity. Just remember: don't store sensitive data in the payload, as it is readable by anyone with access to the token.

How JWT Token is Constructed

1️⃣ HEADER
{"alg": "HS256", "typ": "JWT"}
Base64URL encoded → eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
2️⃣ PAYLOAD
{"username": "teppotesti", "exp": 1718111800}
Base64URL encoded → eyJ1c2VybmFtZSI6InRlcHBvdGVzdGkiLCJleHAiOjE3MTgxMTE4MDB9
3️⃣ SIGNATURE
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
Result → SGp1Y2la3EXAMPLE2wR7J_yPaAogwEXAMPLEqj8c
HEADER
+
PAYLOAD
+
SIGNATURE
=
JWT TOKEN
✨ Final JWT Token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlcHBvdGVzdGkiLCJleHAiOjE3MTgxMTE4MDB9.SGp1Y2la3EXAMPLE2wR7J_yPaAogwEXAMPLEqj8c

⚠️ Important: JWT Payload is NOT Encrypted!

The payload is only Base64URL encoded, NOT encrypted. Anyone with the token can decode it using a simple JavaScript function:

Example - Decoding the payload from our JWT:
eyJ1c2VybmFtZSI6InRlcHBvdGVzdGkiLCJleHAiOjE3MTgxMTE4MDB9
Using atob() function in browser console:
atob("eyJ1c2VybmFtZSI6InRlcHBvdGVzdGkiLCJleHAiOjE3MTgxMTE4MDB9")
Result - Anyone can see this:
{"username":"teppotesti","exp":1718111800}
❌ NEVER store in JWT payload:
  • Passwords or password hashes
  • Social security numbers
  • Credit card information
  • Personal health information
  • API keys or secrets
  • Any other sensitive data
✓ Safe to store in JWT payload:
  • Username or user ID
  • User roles (admin, user, etc.)
  • Expiration time
  • Non-sensitive user preferences
Remember: The signature ensures the token hasn't been modified, but it does NOT prevent the payload from being read.

🔒 Can You Get the JWT Secret from the Signature?

NO! This is a critical difference between the payload and the signature:

📦 Payload (Encoding)
eyJ1c2VybmFtZSI6InRlcH...
Base64URL Encoding
↓ Reversible (two-way)
✓ atob() → JSON visible
🔐 Signature (Hash)
SGp1Y2la3EXAMPLE2wR7J...
HMAC-SHA256 Hash
↓ Irreversible (one-way)
✗ Cannot decode back to secret
📚 Important: Hashing vs Encryption vs Encoding

Many people confuse these concepts. Let's clarify:

Encoding
• Reversible (two-way)
• No key needed
• Not for security
• Example: Base64URL
JWT Payload uses this
Hashing
• One-way only
• Cannot be reversed
• Creates "fingerprint"
• Example: SHA-256
JWT Signature uses this
Encryption
• Reversible (two-way)
• Needs key to decrypt
• For confidentiality
• Example: AES, RSA
JWT does NOT use this
Why can't you reverse the signature?

The signature is created using a hash function (HMAC-SHA256), NOT encryption. Hash functions are designed to be:

  • One-way: Easy to compute hash from input, mathematically impossible to reverse
  • Deterministic: Same input always produces same hash output
  • Collision-resistant: Nearly impossible to find two different inputs with same hash

Key point: Hashing creates a "digital fingerprint" of the data. You cannot reconstruct the original data from the fingerprint, but you can verify if data matches the fingerprint.

⚠️ Only way to "crack" the secret:
  • Brute force: Try billions of possible secrets
  • Dictionary attack: Test common passwords like "secret123", "myPassword"

If your secret is weak (e.g., "mySecret123") → Can be cracked in minutes
If your secret is strong (crypto.randomBytes(64)) → Practically impossible to crack

💡 Summary:
  • Payload: Anyone can decode (Base64URL) → Assume it's public
  • Signature: Cannot be reversed → Secret is safe if strong
  • Purpose of signature: Verify integrity, NOT hide secret
This is why using crypto.randomBytes(64) for your JWT secret is critical!
Bearer Token vs JWT - What's the Difference?

Many people confuse Bearer Tokens and JWT. Let's clarify the difference:

📦 Bearer Token

Authentication scheme/mechanism (OAuth 2.0 standard)

  • Means: "The bearer (holder) of this token gets access"
  • Header format: Authorization: Bearer <token>
  • Token can be: JWT, random string, opaque token, or anything
  • Purpose: Defines HOW the token is transmitted

🎫 JWT (JSON Web Token)

Token format/structure (specific standard)

  • Structure: Header.Payload.Signature (three parts)
  • Self-contained: Contains information within itself
  • Standard: Specific JSON-based format (RFC 7519)
  • Purpose: Defines WHAT the token contains
🔗 The Connection:
  • JWT is OFTEN used as a Bearer token (most common use case)
  • But Bearer token is NOT always JWT (can be other formats)
Examples:
// JWT used as Bearer token (most common)
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

// Opaque token as Bearer token
Authorization: Bearer 2YotnFZFEjr1zCsicMWpAA

// Simple random string as Bearer token
Authorization: Bearer abc123xyz456random
💡 Analogy to understand:
  • Bearer: "The envelope" (how the token is delivered)
  • JWT: "The letter content" (what the token contains)

You can send different types of letters (JWT, plain text, encrypted data) in the same type of envelope (Bearer authentication).

⚡ In this tutorial:

When you see Authorization: Bearer eyJhbGciOi..., you are using:

  • Bearer authentication scheme to transmit the token
  • JWT format for the token itself

Both concepts work together but serve different purposes!



Toggle Menu