Understanding JWT Tokens: A Complete Guide

Introduction

JSON Web Tokens (JWT) have become the standard for secure data transmission between parties. Whether you're building authentication systems, API integrations, or microservices architecture, understanding JWT is essential for modern web development.

In this guide, we'll dive deep into how JWTs work, explore their structure, discuss security considerations, and show you practical examples. Plus, learn how to debug JWTs using our free JWT Decoder tool in OptiLab.

What is a JWT?

A JSON Web Token is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure.

In simpler terms, JWTs are like digital passports that contain information about a user and are cryptographically signed to verify their authenticity.

JWT Structure

A JWT consists of three parts separated by dots (.):

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

1. Header

The header typically consists of two parts: the type of token (JWT) and the signing algorithm being used.

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

2. Payload

The payload contains the claims. Claims are statements about an entity (typically, the user) and additional data.

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

3. Signature

To create the signature, you take the encoded header, encoded payload, a secret, and sign it using the algorithm specified in the header.

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

Common JWT Claims

Standard claims that you'll frequently encounter:

  • iss (Issuer): Identifies who issued the JWT
  • sub (Subject): Identifies the subject of the JWT
  • aud (Audience): Identifies recipients that should process the JWT
  • exp (Expiration): Unix timestamp when the token expires
  • nbf (Not Before): Unix timestamp before which token is invalid
  • iat (Issued At): Unix timestamp when the token was issued
  • jti (JWT ID): Unique identifier for the token

JWT Flow: Authentication Example

Here's how JWT authentication typically works in a web application:

  1. User Login: User submits credentials to the server
  2. Token Creation: Server verifies credentials and creates a JWT
  3. Token Response: Server sends JWT back to the client
  4. Token Storage: Client stores JWT (localStorage, cookie, etc.)
  5. Token Sending: Client includes JWT in subsequent requests
  6. Token Verification: Server verifies JWT signature and processes request

When to Use JWT

JWTs are ideal for:

  • Authentication: Single Sign-On (SSO) implementations
  • Authorization: Passing user permissions between services
  • Information Exchange: Securely transmitting data between parties
  • API Security: Securing RESTful APIs and microservices
  • Stateless Sessions: When you don't want server-side session storage

JWT vs Session-Based Authentication

JWT Sessions
Stateless - no server storage needed Stateful - requires session storage
Works well for microservices Better for monolithic apps
Cross-domain friendly Same-domain only
Cannot be easily revoked Can be revoked immediately
Larger payload size Smaller (just session ID)

Security Best Practices

1. Always Use HTTPS

JWTs sent over HTTP can be intercepted. Always use HTTPS in production.

2. Set Expiration Times

Never create tokens that never expire. Short-lived tokens are more secure.

{
  "exp": Math.floor(Date.now() / 1000) + (60 * 15)
}

3. Use Strong Secret Keys

Your secret key should be long, random, and stored securely. Use environment variables.

4. Validate All Claims

Don't just validate the signature. Check issuer, audience, and expiration.

5. Don't Store Sensitive Data

JWT payloads are base64 encoded, not encrypted. Anyone can decode and read them.

6. Implement Refresh Tokens

Use short-lived access tokens with longer-lived refresh tokens for better security.

Debugging JWTs with OptiLab

When working with JWTs, you often need to decode and inspect them. Our JWT Decoder tool in OptiLab makes this easy:

  • Decode: View header, payload, and signature sections
  • Validate: Verify token structure and format
  • Inspect: Read all claims in human-readable format
  • Debug: Quickly identify token issues during development

Implementing JWT in Node.js

Here's a practical example using the jsonwebtoken package:

Installation

npm install jsonwebtoken

Creating a Token

const jwt = require('jsonwebtoken');

function generateToken(user) { return jwt.sign( { userId: user.id, email: user.email, role: user.role }, process.env.JWT_SECRET, { expiresIn: '15m', issuer: 'https://cekapcoder.com', audience: 'cekapcoder-api' } ); }

Verifying a Token

function verifyToken(token) {
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET, {
      issuer: 'https://cekapcoder.com',
      audience: 'cekapcoder-api'
    });
return { valid: true, decoded };

} catch (error) { return { valid: false, error: error.message }; } }

Common JWT Algorithms

HS256 (HMAC with SHA-256)

Uses a shared secret. Simple and fast, but secret must be kept secure on both sides.

RS256 (RSA Signature with SHA-256)

Uses public/private key pair. More secure for distributed systems. Private key signs, public key verifies.

ES256 (ECDSA using P-256 and SHA-256)

Similar to RS256 but uses elliptic curve cryptography. Smaller signatures, better performance.

JWT Troubleshooting

"Invalid Token" Errors

  • Check if the token is expired
  • Verify the signature matches your secret/key
  • Ensure the algorithm matches what was used to sign
  • Use JWT Decoder to inspect the token

Token Too Large

  • Reduce payload size by removing unnecessary claims
  • Use reference tokens instead of self-contained tokens
  • Consider storing user data in your database and just include an ID

Conclusion

JWTs are a powerful tool for modern web applications. They're stateless, scalable, and work great for distributed systems. However, they require careful attention to security practices.

Key takeaways:

  • Always use HTTPS and strong secret keys
  • Set appropriate expiration times
  • Never store sensitive data in JWT payloads
  • Use refresh tokens for better user experience
  • Validate all claims, not just the signature

Ready to work with JWTs? Try our JWT Decoder tool in OptiLab to inspect and debug your tokens.

Further Reading

Share this post