12 min read

Guide · Developer security

JWT Playground Tutorial: Hands-On Learning

Master JSON Web Tokens through interactive examples. Learn to create, decode, and verify JWTs step-by-step with real-world scenarios and security best practices.

What You'll Learn

JWT Anatomy

  • Header structure and algorithms
  • Payload claims and data
  • Signature verification process
  • Base64URL encoding explained

Practical Skills

  • Create and sign JWTs
  • Decode and validate tokens
  • Handle expiration times
  • Debug common issues

Security Focus

  • Algorithm security (HS256 vs RS256)
  • Secret management
  • Attack prevention
  • Production deployment

JWT Basics: Understanding the Structure

Anatomy of a JWT

A JWT consists of three parts separated by dots (.). Let's break down each component:

JWT token
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Header

Contains algorithm and token type

Header
{
  "alg": "HS256",
  "typ": "JWT"
}

Payload

Contains the claims/data

Payload
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

Signature

Verifies token integrity

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

Interactive Exercise 1: Creating Your First JWT

Goal: Create a Basic JWT. Let's create a JWT for a user authentication scenario. You'll learn how each component contributes to the final token.

Step 1: Define the Header

The header specifies the algorithm used for signing. HS256 (HMAC with SHA-256) is common for simple use cases.

Header JSON
{
  "alg": "HS256",
  "typ": "JWT"
}

Base64URL Encoded: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Try it: Use our JWT generator to experiment with different algorithms like RS256 or ES256.

Step 2: Create the Payload

The payload contains claims about the user and session. Include essential information but keep it lean.

Payload JSON
{
  "sub": "user123",          // Subject (user ID)
  "name": "Alice Johnson",   // Custom claim
  "role": "user",           // User role
  "iat": 1640995200,        // Issued at (timestamp)
  "exp": 1641001200         // Expires at (timestamp)
}

Base64URL Encoded: eyJzdWIiOiJ1c2VyMTIzIiwibmFtZSI6IkFsaWNlIEpvaG5zb24iLCJyb2xlIjoidXNlciIsImlhdCI6MTY0MDk5NTIwMCwiZXhwIjoxNjQxMDAxMjAwfQ

Security note:
  • Never include passwords or sensitive data in the payload
  • JWTs are encoded, not encrypted (readable with base64 decode)
  • Use short expiration times (15-60 minutes) for access tokens

Step 3: Generate the Signature

The signature ensures the token hasn't been tampered with. It's created using the header, payload, and a secret key.

Signature algorithm
signature = HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  "your-secret-key"
)

Example Secret: mySecureSigningKey2024!
Resulting Signature: k8GTeGOJhBtC1esXPRYGHQMnM2s6i4DYvAkGNDqHlJM

Complete JWT Token

Combining all three parts with dots creates your final JWT:

Complete JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMTIzIiwibmFtZSI6IkFsaWNlIEpvaG5zb24iLCJyb2xlIjoidXNlciIsImlhdCI6MTY0MDk5NTIwMCwiZXhwIjoxNjQxMDAxMjAwfQ.k8GTeGOJhBtC1esXPRYGHQMnM2s6i4DYvAkGNDqHlJM
Congratulations! You've created your first JWT. This token can now be used for authentication.

Interactive Exercise 2: Decoding and Validating JWTs

Goal: Understand JWT Verification. Learn how to decode JWT components and verify their integrity. This is crucial for secure authentication.

Sample JWT to Analyze

Let's decode this JWT step by step to understand its contents:

Sample JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyNDU2IiwibmFtZSI6IkJvYiBTbWl0aCIsImFkbWluIjp0cnVlLCJpYXQiOjE2NDA5OTUyMDAsImV4cCI6MTY0MTAwMTIwMH0.t6tH7SqE1X-6SxlsEoaVQFhpvEp7WLLhRqXXXjQfbTc

1. Decode Header

Encoded: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Decoded header
{
  "alg": "HS256",
  "typ": "JWT"
}

2. Decode Payload

Encoded: eyJzdWIiOiJ1c2VyNDU2Ii...

Decoded payload
{
  "sub": "user456",
  "name": "Bob Smith",
  "admin": true,
  "iat": 1640995200,
  "exp": 1641001200
}

3. Verify Signature

Signature: t6tH7SqE1X-6SxlsEoaVQF...
Verification: valid with secret "mySecretKey123"

Validation Checklist

When receiving a JWT, perform these validation steps:

Structure Validation

  • Three parts separated by dots
  • Valid Base64URL encoding
  • Header contains required fields
  • Payload has valid JSON structure

Security Validation

  • Signature verification passes
  • Token hasn't expired (exp claim)
  • Token is not used before valid time (nbf)
  • Issuer is trusted (iss claim)
Common validation mistakes:
  • Trusting tokens without signature verification
  • Not checking expiration times
  • Accepting tokens with "none" algorithm
  • Using weak or default secrets

Real-World Scenarios

Scenario 1: User Login System

Building a secure login system where JWTs are issued after successful authentication.

Implementation Steps:

  1. User Authentication: Verify username and password against database
  2. Generate JWT: Create token with user ID, role, and expiration
  3. Return Token: Send JWT to client (avoid storing in localStorage for XSS protection)
  4. Token Usage: Client includes JWT in Authorization header for API requests
  5. Token Verification: Server validates signature and expiration on each request
Best practices:
  • Use secure HTTP-only cookies for storage
  • Implement token refresh mechanism
  • Set appropriate expiration times
  • Include rate limiting
Common pitfalls:
  • Storing tokens in localStorage
  • Not implementing logout/revocation
  • Using long expiration times
  • Exposing sensitive data in claims

Scenario 2: API Access Control

Using JWTs to control access to API endpoints based on user roles and permissions.

Sample API JWT payload
{
  "sub": "api_user_789",
  "iss": "api.mycompany.com",
  "aud": ["api.mycompany.com", "mobile.mycompany.com"],
  "exp": 1641001200,
  "iat": 1640997600,
  "scope": ["read:users", "write:posts", "admin:dashboard"],
  "rate_limit": 1000
}
1Scope-based permissions: define what actions the token holder can perform
2Audience validation: ensure token is intended for your API
3Rate limiting: include usage limits to prevent abuse

Scenario 3: Microservices Communication

Secure communication between microservices using JWTs for service-to-service authentication.

Service JWT example
{
  "sub": "order-service",
  "iss": "auth-service",
  "aud": ["inventory-service", "payment-service"],
  "exp": 1641001200,
  "service_id": "order-svc-001",
  "permissions": ["read:inventory", "write:payments"]
}

Each service validates tokens before processing requests, ensuring only authorized services can interact.

Security Deep Dive

Algorithm Confusion Attacks

Attackers change the algorithm from RS256 to HS256, then use the public key as the HMAC secret. Prevention: always specify expected algorithms in your verification code.

Node.js
// Good: Specify allowed algorithms
jwt.verify(token, secret, { algorithms: ['HS256'] });

// Bad: Accept any algorithm
jwt.verify(token, secret);

"None" Algorithm Bypass

Some JWT libraries accept "none" algorithm, which skips signature verification entirely.

Example malicious header
{
  "alg": "none",
  "typ": "JWT"
}
Prevention: Explicitly reject "none" algorithm in your code.

Weak Secret Keys

Short or predictable secrets can be brute-forced, allowing attackers to forge tokens.

Weak Secrets

  • "secret"
  • "password123"
  • Company name
  • Dictionary words

Strong Secrets

  • 256+ bit random keys
  • Use crypto.randomBytes(32)
  • Store in environment variables
  • Rotate regularly

Security Best Practices

Token Management

  • Short expiration: 15-60 minutes for access tokens
  • Refresh tokens: Longer-lived but revocable
  • Revocation list: Track and invalidate compromised tokens
  • Secure storage: HTTP-only cookies preferred

Implementation Security

  • Algorithm allowlisting: Specify exact algorithms
  • Audience validation: Verify aud claim
  • Issuer validation: Verify iss claim
  • Time validation: Check iat, exp, nbf claims

Troubleshooting Common Issues

"Invalid Signature" Errors

Common causes:
  • Using different secrets for signing and verification
  • Algorithm mismatch (e.g., signed with HS256, verified with RS256)
  • Token corruption during transmission
  • Clock skew between servers

Debug steps: Log the exact token, algorithm, and secret being used. Compare with original signing parameters.

"Token Expired" Errors

Solutions:
  • Implement automatic token refresh before expiration
  • Synchronize server clocks (use NTP)
  • Add clock skew tolerance (leeway) to verification
  • Use appropriate expiration times for your use case

Implementation tip: Refresh tokens when they're 80% through their lifespan.

"Malformed Token" Errors

Validation steps:
  • Check token format: three parts separated by dots
  • Verify Base64URL encoding (not regular Base64)
  • Ensure header and payload are valid JSON
  • Check for extra whitespace or newlines

Quick test: Use jwt.io to decode your token and check for formatting issues.

Next Steps

Practice Exercises

  • Build a complete login system with JWT
  • Implement token refresh mechanism
  • Create role-based access control
  • Set up JWT revocation system

Advanced Topics

  • JWE (JSON Web Encryption) for sensitive data
  • JWK (JSON Web Keys) for key rotation
  • OAuth 2.0 integration with JWTs
  • Performance optimization for high-traffic apps
Pro tip: Generate secure JWT secrets and experiment with different algorithms using our JWT secret generator. Practice makes perfect when it comes to JWT security!