ENGINEERING COMMAND CENTER

LIVE ENGINEERING STATUS
Available for Full-Time Roles
Open to opportunities worldwide
RoleSenior Full Stack Engineer
Focus AreaBackend • Cloud • AI
Experience5+ Years
TimezoneFlexible
CurrentlyActively Looking
← Back to Engineering Articles
Category: Security

How JWT Authentication Works Under the Hood

1. Why I wrote this

As web applications move from monoliths to microservices, traditional session-based cookie verification becomes an infrastructure bottleneck. I wrote this guide to detail the cryptographic mechanics of JSON Web Tokens, demonstrating how stateless authentication maintains security at scale without constant database session lookups.

2. The Problem

In session-based authentication, the server generates a session ID, stores it in database memory (or Redis), and sends it to the client. On every HTTP request, the database must be queried to validate that session. When scaling to multiple server instances:

  • Servers must share session stores (e.g. centralized Redis), introducing latency and single points of failure.
  • In-memory sessions make servers stateful, complicating horizontal container autoscaling.

3. Core Concept

A JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact, self-contained way for securely transmitting information between parties as a JSON object. This information is cryptographically signed, meaning the server can trust the claims without querying a database. It consists of three parts:

  • Header: Defines token type and hashing algorithm (e.g., HS256, RS256).
  • Payload: Contains the claims (user ID, expiration, roles).
  • Signature: Formed by hashing the encoded header, payload, and a secret key.

4. How it works

The token flow consists of: 1. Credentials Validation: User posts login details. 2. Token Signing: Server verifies, signs a payload, and sets short-lived access tokens. 3. Transmission: Client receives token and attaches it to subsequent API headers (Authorization: Bearer <token>) or HttpOnly cookies. 4. Stateless Verification: Server decodes the token and verifies the signature using its private key or secret. If the signature matches and expiration is valid, the request is authorized.

5. Architecture or Flow

The architectural flow of stateless token validation compared to stateful session stores is represented below:

text
[ Client Device ] --( 1. Send Login Credentials )--> [ API Gateway / Load Balancer ]
                                                               |
                                                     ( 2. Routes Authenticator )
                                                               |
                                                    [ Auth Microservice Node ]
                                                               |
                                                     ( 3. Compare Password )
                                                               |
                                                           [ MongoDB ]
                                                               |
                                                ( 4. Sign RS256 Access Token )
                                                               |
[ Client Device ] <--( 5. Set Cookie Token payload )-----------'

Subsequent Authorized API Calls:
[ Client Device ] --( 6. Request with JWT httpOnly cookie )--> [ API Server Node ]
                                                                      |
                                                       ( 7. Decode & Verify Local Signature )
                                                               ( No DB Query Required! )
                                                                      |
                                                       ( 8. Process & Return Data )
[ Client Device ] <--( 9. JSON Response payload )----------------------'

6. Code Example

Below is a Node.js / Express implementation demonstrating RS256 token verification:

javascript
const express = require('express');
const jwt = require('jsonwebtoken');
const fs = require('fs');

const app = express();
// Load public key for token verification (asymmetric signature)
const publicKey = fs.readFileSync('./keys/public.key', 'utf8');

function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1]; // Bearer <JWT>

  if (!token) {
    return res.status(401).json({ error: 'Access token missing' });
  }

  // Verify the signature asymmetrically using RS256 public key
  jwt.verify(token, publicKey, { algorithms: ['RS256'] }, (err, user) => {
    if (err) {
      return res.status(403).json({ error: 'Invalid or expired token' });
    }
    req.user = user;
    next();
  });
}

app.get('/api/protected-resource', authenticateToken, (req, res) => {
  res.json({ data: 'Sensitive telemetry data', user: req.user });
});

7. Security or Performance Considerations

Warning
Token Storage Vulnerabilities: Storing JWTs in browser localStorage leaves them open to Cross-Site Scripting (XSS) attacks. If an attacker injects a script, they can copy the token. Mitigation: Store access tokens inside httpOnly, Secure, and SameSite=Strict cookies. This ensures JavaScript cannot read the token, blocking token theft scripts.
  • RS256 Asymmetric Keys: Chose RS256 over HS256. With HS256, both the signing microservice and the reading APIs need the *same* secret key. If a secondary API is compromised, the secret is leaked and attackers can forge tokens. RS256 uses a private key to sign and a public key to read, letting resource servers verify tokens without granting them signing capabilities.
  • Short Lifetimes & Redis Blacklists: Set access tokens to expire in 15 minutes. To allow users to stay logged in, pair with a rotating refresh token stored in the database. If a user logs out early, blacklist the access token inside a fast Redis table until its natural expiration.

8. Common Mistakes

  • Using the 'none' Algorithm: Older JWT libraries parsed a token header containing {"alg":"none"} and skipped signature verification entirely. Always explicitly specify allowed algorithms (e.g. { algorithms: ['RS256'] }) inside verify hooks.
  • Storing Sensitive Data in Payload: Payload claims are Base64Url-encoded, NOT encrypted! Anyone who intercepts the token can read the user data. Never store passwords, API keys, or personal identification records in the claims.

9. Where I applied it

I implemented this exact architecture in authservice. The microservice utilizes RS256 private keys to sign authentication payload claims, while downstream servers like civicpulse read the tokens using public keys, maintaining absolute system isolation.

10. Key Takeaways

  • JWTs enable stateless authentication, eliminating database read operations on authorized requests.
  • Always sign tokens asymmetrically (RS256) when building microservices to isolate private keys.
  • Enforce httpOnly and SameSite flags on cookies to lock out scripts from reading auth data.
  • Balance security with user convenience by implementing 15-minute access tokens coupled with rotating refresh tokens.
  • Auth Service -Standalone authentication microservice.
  • CivicPulse AI - Integrates the auth token validator middleware to secure reporting routes.
  • Understanding the Node.js Event Loop - Deep dive on concurrency.