Skip to content
← Writing

Demystifying JWT: what a token contains and how it is verified

What a JSON Web Token actually contains, how signing and verification work, and where JWTs go wrong in real authentication flows.

  • 4 min read
Skip to contents
Contents
Title card reading ‘Demystifying JWT’, beside a padlock on a red, yellow and blue striped roundel.

If you’ve ever logged into a web app and stayed logged in without hitting “remember me,” chances are a JWT was at work behind the scenes.

JSON Web Tokens (JWTs) have quietly become the backbone of modern authentication systems. They power APIs, mobile apps, microservices, and even decentralized platforms. But what exactly are they, how do they work, and when should (or shouldn’t) you use them?

The strengths are real, and so are the pitfalls.


What is a JWT?

A JWT (JSON Web Token) is a compact, URL-safe token that represents claims securely between two parties, typically a client and a server.

It’s made up of three parts, separated by dots (.):


xxxxx.yyyyy.zzzzz

The Three Parts

  1. The header describes the token type and signing algorithm.
{
  "alg": "HS256",
  "typ": "JWT"
}
  1. The payload contains the claims, meaning the data about the user or session.
{
  "sub": "1234567890",
  "name": "Mahmudul Alam",
  "admin": true,
  "exp": 1734283200
}
  1. The signature verifies that the token hasn’t been tampered with.
HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

When encoded, it looks like this (shortened for sanity):

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ik1haG11ZHVsIEF
sYW0iLCJhZG1pbiI6dHJ1ZX0.
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

Compact, self-contained, and readable.


How JWT Works (Step-by-Step)

Imagine you’re logging into a web app. Here’s the flow:

  1. Client sends credentials (username/password) to the server.
  2. Server verifies and issues a JWT signed with a secret key.
  3. Client stores the token (often in localStorage or an HTTP-only cookie).
  4. For each subsequent request, the client attaches the JWT in the Authorization header:
Authorization: Bearer <token>
  1. The server validates the token’s signature and expiration time (no database lookup needed).
  2. If valid, the request proceeds as the authenticated user.

This stateless model scales beautifully: no session store required.


JWTs work across distributed systems and microservices without centralized session storage, and they’re compact enough to fit easily in HTTP headers or URLs. Each token is self-contained: it carries all the user information (claims) needed for authorization. They work in browsers, mobile apps, and APIs, and they’re supported across Node.js, Python, Go, Java, Rust, and more.


Common Misconceptions (and Mistakes)

JWT ≠ Encryption

JWTs are signed, not encrypted (by default). That means:

  • Anyone can decode and read the payload.
  • But they cannot modify it without invalidating the signature.

If you need confidentiality, use JWE (JSON Web Encryption).


Long-lived tokens are dangerous

JWTs don’t have a built-in revoke mechanism. If you issue tokens that last too long, they can be stolen and abused.

The fix is to use short-lived access tokens (e.g., 15 minutes) and refresh tokens to reissue them safely.


Don’t store JWT in localStorage

While it’s tempting, it exposes you to XSS attacks. Instead, prefer HTTP-only cookies, which are not accessible via JavaScript.


When to Use JWT — and When Not To

Great Use Cases

  • Single-page apps (SPA) or mobile APIs
  • Microservices that need stateless auth
  • Federated identity systems (OAuth 2.0 / OpenID Connect)
  • Server-to-server authentication

Avoid JWT if:

  • You need to invalidate sessions immediately (use traditional sessions)
  • You’re building a simple monolithic app
  • You don’t need to scale horizontally

Signature Algorithms

Common signing algorithms include:

AlgorithmTypeDescription
HS256SymmetricHMAC + SHA256 using shared secret key
RS256AsymmetricRSA + SHA256 using private/public key pair
ES256AsymmetricElliptic Curve + SHA256 (lightweight, secure)

Prefer RS256 or ES256 for stronger key management.


Example in Node.js (with jsonwebtoken)

import jwt from 'jsonwebtoken';
 
const secret = 'supersecretkey';
 
// Sign a token
const token = jwt.sign({ userId: 42, role: 'admin' }, secret, { expiresIn: '15m' });
 
// Verify a token
try {
  const decoded = jwt.verify(token, secret);
  console.log(decoded);
} catch (err) {
  console.error('Invalid or expired token');
}

JWT vs Session Cookies: Quick Comparison

FeatureJWTSession Cookies
StorageClient-sideServer-side
ScalabilityExcellentLimited
RevocationHardEasy
SecurityDepends on implementationEasier to secure
Use CaseAPIs, SPAs, mobile appsClassic web apps

When JWT Is Worth It

JWTs are incredibly powerful, but like any power tool, they demand responsible use.

Used correctly, they offer scalable, stateless, cross-platform authentication. Used carelessly, they can open serious security vulnerabilities.

Rule of thumb: If your app talks to multiple services or clients, JWT is your friend. If it’s a simple web app, traditional sessions may still be your best bet.


References

  • jwt
  • authentication
  • security
  • web-development

Comments