A Deep-Dive Visual Guide

JWT Demystified

From signed tokens and HMAC hashing, to Redis caching, OAuth 2.0 flows, and OpenID Connect — the complete picture, explained visually.

JSON Web Tokens OAuth 2.0 OpenID Connect Microservices Auth Spring Security Keycloak Redis HS256 vs RS256
Chapter 01

What Is a JWT?

A JWT (JSON Web Token) is a compact, self-contained string that carries information between two parties in a digitally signed package. It looks like random gibberish — but it's exactly three base64-encoded JSON objects stitched together with dots.

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJwcmFzaGFudCIsInJvbGUiOiJBRE1JTiIsInVzZXJJZCI6MTAxLCJleHAiOjE3MTczNDc2MDB9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

■ Header  ·  ■ Payload  ·  ■ Signature

Header

{
  "alg": "HS256"
}

Tells the server which algorithm was used to create the signature, so it knows how to verify it.

Payload (Claims)

{
  "sub": "prashant",
  "role": "ADMIN",
  "userId": 101,
  "exp": 1717347600
}

Your data — identity, roles, permissions, expiry. Readable by anyone. Never put secrets here.

Signature

HMAC_SHA256(
  header + "."
  + payload,
  secretKey
)

Cryptographic proof the token was not tampered with. Cannot be faked without the secret key.

⚠ Critical — Signed ≠ Encrypted

Anyone can base64-decode the header and payload and read the contents. A signed JWT proves the data was not tampered with — it does not hide the data. Never put passwords, card numbers, or sensitive PII in a JWT.

Chapter 02

How the Signature Works

The signature is the entire security model of JWT. HMAC_SHA256 is not encryption — it is a one-way cryptographic fingerprint. You cannot reverse it, but the same inputs always produce the same output. That determinism is the whole trick.

Creating the Token

1
Encode header → eyJhbGciOiJIUzI1NiJ9
2
Encode payload → eyJzdWIiOiJwcmFzaGFudCJ9
3
Join with dot → eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJwcmFzaGFudCJ9
4
Run HMAC_SHA256(above_string, secretKey) → produces fixed-length hash SflKxwRJ...
5
Append as third part → send complete token to client

Verifying — No Storage Needed

Token arrives with signature SflKxwRJ...
Server runs HMAC_SHA256(header + "." + payload, secretKey) again
Match? Token is genuine ✅  |  No match? Payload was modified → reject 401 ❌
💡 The Key Insight

A hacker can read the payload (it's just base64). But without the secret key, they cannot forge a valid signature. Changing "role":"user" to "role":"admin" breaks the signature — the server rejects it immediately.

🔬 Live JWT Token Explorer
Generated JWT Token

      

      
HMAC_SHA256(
  header.payload,
  secretKey
)
→ simulated
  (real signing
   needs backend)
Chapter 03

Expiry, Stateless Auth & Redis

JWT expiry is just the exp field in the payload — a Unix timestamp. The server compares it against the current time. Pure math. No database. This statelessness is JWT's biggest architectural advantage.

Token TypeTypical ExpiryWhy
Access Token15 min – 1 hourShort-lived, limits blast radius if stolen
Refresh Token7 – 30 daysSilently obtains a new access token without re-login

The Redis Caching Pattern

Even though JWT is stateless by design, every serious production system adds Redis between the API Gateway and Keycloak. Here's why:

API Gateway

Receives every request with Bearer token

→ check →
Redis Cache
key: "jwt:userId:101"
value: "eyJhbG..."
TTL: 3600s
← hit / miss ←
Result

Found → forward request
Not found → 401 Reject

BenefitHow Redis Enables It
SpeedMicrosecond lookup vs. a network call to Keycloak on every single request
LogoutDelete key from Redis → token instantly dead, even before expiry
Role changeDelete key → forces re-login → fresh token with new role from DB
Chapter 04

HS256 vs RS256

In microservices, this algorithm choice is critical. HS256 shares one secret across all services. RS256 uses a public/private key pair — and that changes the entire security posture.

HS256 — Shared Secret

Signs withsecretKey
Verifies withsame secretKey
Who holds itevery service
If compromisedanyone can forge tokens
Best forsingle service, internal tools

RS256 — Public / Private Key Pair

Signs withprivate key (Keycloak only)
Verifies withpublic key (any service)
Who holds itprivate key never leaves Keycloak
If compromisedcan verify only, never forge
Best formicroservices, enterprise, PSD2
🔑 JWKS Endpoint — How Services Get the Public Key

Keycloak exposes: https://keycloak.company.com/realms/myrealm/protocol/openid-connect/certs. Every microservice calls this once at startup, downloads the public key, and uses it forever. No secret ever leaves Keycloak. No key distribution problem.

Chapter 05

Who Creates the JWT & How Wrong Access Is Prevented

A dedicated Auth Server — Keycloak, Auth0, Okta, or your own Spring Boot service — is the only entity that creates tokens. Before issuing one, it runs a strict verification pipeline.

1

Verify Identity

Check username + password against the user database. Wrong credentials → reject 401 immediately.

2

Fetch Roles from DB

SELECT role, permissions FROM users WHERE username = 'prashant' → returns role=ADMIN

3

Check Additional Conditions

Is account active? Email verified? MFA passed? IP whitelisted? In PSD2 — did the user explicitly consent to the requested scope?

4

Build the Payload

The token is a snapshot of what the DB said at login time: role, permissions, scope, iat, exp.

5

Sign & Issue

HMAC_SHA256(header + payload, secretKey) → final token sent to the client.

🛡 Three Independent Locks Against Wrong Access

Rahul cannot get ADMIN in his token because: (1) he cannot modify the payload — signature breaks; (2) he cannot forge a new signature — no secret key; (3) he cannot use Prashant's token — "sub":"prashant" is baked inside it. Three independent security guarantees.

Chapter 06

OAuth 2.0 Grant Types

OAuth 2.0 defines five ways to request a token — called "grant types" or "flows". Choosing the right one for your scenario is a key architectural decision.

Modern Standard

Authorization Code Flow

Web apps with a backend server. User is redirected to the auth server, logs in, receives a short-lived code — not the token directly. The backend exchanges the code for the token. Token never touches the browser URL bar.

Modern Standard

Authorization Code + PKCE

Mobile apps and SPAs. Same as above but adds a code verifier/challenge pair to prevent interception attacks. Used when client secrets cannot be safely stored on the device.

Machine-to-Machine

Client Credentials Flow

Microservice-to-microservice, no human involved. The Order Service sends its clientId + clientSecret to the auth server and receives a JWT to call the Payment Service.

Legacy — Avoid

Resource Owner Password (ROPC)

User hands username + password directly to your app, which forwards them to the auth server. The app sees the password — inherently risky. Only use for legacy system migration.

Deprecated

Implicit Flow

Old SPAs received tokens directly in the browser URL fragment. The token was exposed in browser history and server logs. Fully replaced by Authorization Code + PKCE.

🏦 PSD2 / Open Banking Context

In PSD2 work, Authorization Code Flow is mandatory. The bank's customer logs in on the bank's own page and grants explicit consent before any Third Party Provider can touch their account data. That consent step is precisely what Authorization Code Flow is designed to enforce.

Chapter 07

JWT vs OAuth 2.0 vs OpenID Connect

These three are layers, not alternatives. Each solves a distinct problem.

📦

JWT — Token Format Only

Just a standard way to package and sign data. Can be used completely standalone — no OAuth, no OIDC required. Your own Spring Boot auth service can issue JWTs directly without either framework.

🔐

OAuth 2.0 — Authorization Framework

Defines how tokens are requested and issued. Answers: "Can this app access this resource on behalf of this user?" Built for third-party access delegation. Uses JWT as its token format.

🪪

OpenID Connect — Identity Layer on OAuth

Built on top of OAuth 2.0. Adds a standardized way to ask "who is this user?" via an ID Token and a /userinfo endpoint. Enables SSO and "Login with Google" without custom integrations per provider.

OIDC: Registration + Login in One Shot

When a user clicks "Login with Google", your app has no record of them. OIDC provides their identity — and your app handles registration and login in a single seamless flow.

1

Google authenticates the user

Login happens on Google's own page. Your app never sees the password.

2

Your app calls /userinfo

Google returns: { "sub": "g-101", "name": "Prashant Sharma", "email": "prashant@gmail.com" }

3

Registration + Login in one shot

New user? Create their record in your DB from the OIDC data. Existing user? Log them straight in. Zero forms, zero email verification, zero password creation.

4

Your own JWT is issued

Now your JWT enters the microservices world — carrying role, userId, and scope for all downstream services.

🔑 The sub Field is Everything

The sub claim is Google's permanent unique identifier for that user. Names change, emails change — sub never does. Always map your DB user to googleSub, not email. This is the stable foreign key to the identity provider.

JWT AloneOAuth 2.0OpenID Connect
Third-party access
Know who the user isCustom onlyNot standardized✓ Standardized
SSO across apps
Login with Google/GitHubNot standard
Chapter 08

The Complete Production Architecture

Here is how all the pieces work together in a real microservices system — the kind of answer that separates a Senior Engineer from a Solution Architect in an interview.

USER
Clicks "Login" — credentials sent to Auth Server (Keycloak)
KEYCLOAK
Verifies credentials, fetches role from DB, checks conditions, builds payload, signs with RS256 private key
KEYCLOAK
Stores token in Redis: key=jwt:userId:101, TTL=3600s
KEYCLOAK
Returns JWT to user / client application
USER
Every request carries Authorization: Bearer <token>
API GW
Checks Redis — found? Forward request. Not found? 401 Reject. No Keycloak call needed.
SERVICE
Verifies signature with Keycloak's public key (loaded from JWKS endpoint at startup)
SERVICE
Reads role and scope from payload → grants or denies access. Zero DB hit.
🏆 The Architect-Level Summary

Keycloak = OIDC + OAuth 2.0 + JWT in one place. Configure once — it handles login, Google SSO via OIDC, JWT creation with RS256, token refresh, Redis caching, scope management, and JWKS public key distribution. Every microservice verifies tokens independently, stateless, with zero DB hits per request. Infinitely scalable. This is the industry-standard pattern for enterprise microservices auth — including PSD2 Open Banking.