DEV Community

arenasbob2024-cell
arenasbob2024-cell

Posted on • Originally published at viadreams.cc

JWT Tokens Explained: A Developer's Complete Guide

What Are JWT Tokens?

JSON Web Tokens (JWT) are a compact, URL-safe way to represent claims between two parties. They are widely used for authentication and authorization in modern web applications. Instead of storing session data on the server, JWTs allow stateless authentication by encoding user information directly into the token.

JWT Structure: Three Parts

A JWT consists of three Base64URL-encoded parts separated by dots:

header.payload.signature
Enter fullscreen mode Exit fullscreen mode

1. Header

The header specifies the token type and the signing algorithm:

{
  "alg": "HS256",
  "typ": "JWT"
}
Enter fullscreen mode Exit fullscreen mode

2. Payload

The payload contains the claims — statements about the user and additional metadata:

{
  "sub": "1234567890",
  "name": "Alice Developer",
  "iat": 1516239022,
  "exp": 1516242622,
  "role": "admin"
}
Enter fullscreen mode Exit fullscreen mode

Common registered claims include:

  • iss — Issuer
  • sub — Subject (user ID)
  • exp — Expiration time
  • iat — Issued at
  • aud — Audience

3. Signature

The signature ensures the token has not been tampered with:

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)
Enter fullscreen mode Exit fullscreen mode

How JWT Authentication Works

Here is the typical JWT authentication flow:

  1. The user sends credentials (username + password) to the server.
  2. The server verifies credentials and generates a JWT.
  3. The client stores the JWT (usually in memory or an httpOnly cookie).
  4. On each subsequent request, the client sends the JWT in the Authorization header.
  5. The server verifies the token signature and extracts user data from the payload.

Creating JWTs in Node.js

Install the jsonwebtoken package:

npm install jsonwebtoken
Enter fullscreen mode Exit fullscreen mode

Signing a Token

const jwt = require('jsonwebtoken');

const SECRET = process.env.JWT_SECRET || 'your-secret-key';

function generateToken(user) {
  const payload = {
    sub: user.id,
    name: user.name,
    role: user.role
  };

  return jwt.sign(payload, SECRET, {
    expiresIn: '1h',
    issuer: 'myapp.com'
  });
}

const token = generateToken({ id: 42, name: 'Alice', role: 'admin' });
console.log('Token:', token);
Enter fullscreen mode Exit fullscreen mode

Verifying a Token

function verifyToken(token) {
  try {
    const decoded = jwt.verify(token, SECRET, {
      issuer: 'myapp.com'
    });
    console.log('Valid token. User:', decoded.sub);
    return decoded;
  } catch (err) {
    if (err.name === 'TokenExpiredError') {
      console.error('Token has expired');
    } else if (err.name === 'JsonWebTokenError') {
      console.error('Invalid token:', err.message);
    }
    return null;
  }
}
Enter fullscreen mode Exit fullscreen mode

Express Middleware Example

function authMiddleware(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'No token provided' });
  }

  const token = authHeader.split(' ')[1];
  const decoded = verifyToken(token);

  if (!decoded) {
    return res.status(403).json({ error: 'Invalid or expired token' });
  }

  req.user = decoded;
  next();
}

app.get('/api/profile', authMiddleware, (req, res) => {
  res.json({ userId: req.user.sub, name: req.user.name });
});
Enter fullscreen mode Exit fullscreen mode

Common JWT Security Mistakes

1. Storing Tokens in localStorage

localStorage is accessible to any JavaScript on the page, making it vulnerable to XSS attacks. Prefer httpOnly cookies or in-memory storage.

2. Not Validating the Algorithm

Always specify the expected algorithm during verification to prevent algorithm confusion attacks:

// Secure: specify the algorithm explicitly
jwt.verify(token, SECRET, { algorithms: ['HS256'] });
Enter fullscreen mode Exit fullscreen mode

3. Using Weak Secrets

For HMAC-based signing, use a cryptographically strong secret of at least 256 bits. For production systems, consider using RS256 with an RSA key pair.

4. Missing Expiration

Always set an exp claim. Tokens without expiration remain valid indefinitely if compromised.

5. Putting Sensitive Data in the Payload

The payload is only Base64-encoded, not encrypted. Never include passwords, credit card numbers, or other secrets.

JWT vs Server-Side Sessions

Aspect JWT Sessions
Storage Client-side Server-side
Scalability Stateless, easy to scale Requires shared session store
Revocation Difficult (needs blocklist) Immediate
Size Larger per-request overhead Small session ID
Use case APIs, microservices, SPAs Traditional web apps

JWTs excel in distributed systems and API-first architectures. Sessions are simpler when you need immediate revocation and have a monolithic server.

Try It Yourself

Need to quickly inspect or decode a JWT token? Use the DevToolBox JWT Decoder to paste any token and instantly see its header, payload, and signature verification status — no sign-up required.

Top comments (0)