FlowingDev

JWT, explained: the token that carries its own passport

Discover JSON Web Tokens (JWT), the compact, self-contained standard for securely transmitting information between parties as a JSON object.

Try the tool: JWT Viewer

In one sentence

A JSON Web Token (JWT) is a compact, URL-safe way to represent claims to be transferred between two parties, typically used for authentication and authorization in a way that can be verified and trusted.

The problem it solves

In the before times—say, the early 2000s—if you logged into a website, the server would create a "session" for you. It was like a little file on the server that said, "User 123 is logged in and has put a rubber chicken in their shopping cart." The server would give your browser a tiny cookie with a session ID, like a coat check ticket. On every subsequent request, your browser presented the ticket, the server looked it up, found your file, and remembered who you were.

This worked fine for a single, monolithic server. But then the web exploded. We got microservices, single-page applications (SPAs), and mobile apps all talking to the same backend. Now, your login request might go to Server A, but your next request to fetch your profile might go to Server B. How does Server B know about the session file on Server A?

You could force a user to always talk to the same server ("sticky sessions"), but that's a bottleneck. You could create a centralized session database (like Redis) that all servers share, but that's another piece of infrastructure to manage and another point of failure.

The core problem is statefulness. The server has to remember you.

JWTs (pronounced "jots") flipped this idea on its head. What if the user could carry their own proof of identity, like a passport? The token itself would contain all the information the server needs: who the user is, what they're allowed to do, and when their access expires. The server doesn't have to remember anything between requests. This is stateless authentication, and it's the key to building scalable, distributed systems. The server just needs to check if the passport (the JWT) is valid and not forged.

How it works under the hood

A JWT isn't an inscrutable blob of gibberish. It's a very specific, structured string made of three parts, separated by dots (.).

xxxxx.yyyyy.zzzzz

Let's break down each part.

The Header (The "Type" Tag)

The first part is the header. It's a simple JSON object that contains metadata about the token itself, primarily the signing algorithm used and the type of the token.

{
  "alg": "HS256",
  "typ": "JWT"
}
  • alg: The signing algorithm. HS256 means this token is signed with HMAC-SHA256, a symmetric algorithm (more on that in a bit). Other common options include RS256 (using an RSA public/private key pair).
  • typ: The token type. For JWTs, this is just "JWT".

This JSON is then Base64Url encoded to produce the first part of the token. Base64 is an encoding scheme, not encryption. It just turns binary data into a text string that's safe to transmit over the web. Think of it like writing "THIS IS A POSTCARD" on the back of a postcard—anyone who intercepts it can read it.

The Payload (The "Claims" Department)

The second part is the payload. This is the good stuff. It's another JSON object that contains the "claims," which are statements about the user (the "subject") and other useful data.

{
  "sub": "10987-23456-98765",
  "name": "Grace Hopper",
  "admin": true,
  "iat": 1516239022,
  "exp": 1516242622
}

Claims come in three flavors:

  • Registered Claims: These are a set of predefined, recommended claims to provide interoperability. They're not mandatory, but they're super useful.
Claim Name Description
iss Issuer Who issued the token (e.g., https://api.mycoolsite.com).
sub Subject The user or entity the token is about (e.g., a user ID).
aud Audience Who the token is intended for (e.g., https://api.mycoolsite.com).
exp Expiration Time When the token expires. A numeric Unix timestamp (seconds since epoch).
iat Issued At When the token was issued. Also a Unix timestamp.
  • Public Claims: These are custom claims that you create, but to avoid naming collisions, they should be defined in the IANA JSON Web Token Claims registry or be a URI that contains a collision-resistant namespace.
  • Private Claims: These are the most common custom claims, created to share information between parties that agree on using them (like admin: true in our example). This is where you put your application-specific data.

Just like the header, the entire payload JSON is Base64Url encoded to form the second part of the JWT. Again, this is not encrypted. Never put sensitive information like passwords in the payload.

The Signature (The Tamper-Proof Seal)

This is the part that provides the security. The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn't changed along the way.

It's created by taking the encoded header, the encoded payload, a secret key, and running them through the algorithm specified in the header. For our HS256 example, the process looks like this:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  your-256-bit-secret
)

The punchline: a secret is used that only the server knows. When the server receives a JWT, it re-runs this exact same calculation with the header and payload it received. If the signature it generates matches the signature on the token, the server knows two things:

  1. Authenticity: The token was created by someone who knows the secret key (i.e., the server itself).
  2. Integrity: The header and payload have not been tampered with. If an attacker changed "admin": false to "admin": true" in the payload, the signature would no longer match.

This signature is the tamper-proof holographic seal on our passport.

Real-world stories

The Microservices Maze

A fast-growing e-commerce company, "ScaleFast," decided to break up its giant, monolithic backend into a fleet of microservices: one for users, one for orders, one for inventory, etc. The old system used a server-side session. But in the new world, how does the OrderService know that a request really came from a logged-in user, without having to call the UserService on every single request? That would be slow and defeat the purpose of decoupling.

The solution was JWT. When a user logs in, the new AuthService issues a JWT containing the userId and their roles. The user's browser then includes this JWT in the Authorization header of every request to other microservices. The OrderService and InventoryService don't need to talk to the AuthService; they just need to know the shared secret key. They can independently verify the JWT's signature, trust the userId inside, and process the request.

Lesson: JWTs are the lingua franca of microservice authentication, enabling services to be stateless and independently verifiable.

The Single-Page App Saga

A developer named Alex was building a slick React dashboard. The frontend was a Single-Page Application (SPA) served from a static host, and it talked to a separate backend API. Alex was wrestling with old-school cookie-based authentication, running into a nightmare of Cross-Origin Resource Sharing (CORS) issues because the frontend and backend were on different domains.

The team switched to JWT. Now, after a user logs in with their username and password, the API sends back a JWT. Alex's React app stores this token in memory and attaches it to every API call: Authorization: Bearer <the-jwt>. The API backend is stateless; it just checks the bearer token on each incoming request. No more CORS cookie headaches.

Lesson: JWTs provide a clean, portable credential that works beautifully for decoupling modern frontend applications from backend APIs.

Common mistakes and traps

  • Putting sensitive data in the payload. Stop! The payload is Base64Url encoded, which is trivially reversible. It is not encrypted. Anyone who gets their hands on the token can read the payload. Treat it like a postcard, not a sealed letter.
  • Forgetting to verify the signature. What's the point of a passport's security features if the border agent doesn't check them? Just decoding the payload and trusting its contents without verifying the signature is a catastrophic security vulnerability. An attacker could forge any payload they want.
  • Trusting the alg header blindly. A famous past vulnerability involved attackers creating a token and changing the header to {"alg": "none"}. Some misconfigured libraries would see "none" and "verify" the signature by, well, doing nothing, accepting the forged token as valid. Always have your server enforce a specific, expected algorithm (e.g., HS256).
  • Leaking your symmetric secret key. For HMAC algorithms like HS256, the secret key is the keys to the kingdom. If it leaks, anyone can forge tokens for any user with any permissions. Guard it like a password.
  • Not setting an expiration (exp) claim. A token that lives forever is a huge liability. If it's ever compromised, an attacker can use it indefinitely. Always set a reasonably short expiration time and use a refresh token mechanism for longer-lived sessions.

Why it belongs on your radar

You should think "JWT" whenever you're dealing with authentication or authorization in a distributed environment.

  • You're building an API for a Single-Page App (SPA) or mobile client.
  • You're designing a microservice architecture where services need to trust requests from each other.
  • You need stateless authentication that can scale horizontally without a shared session store.
  • You're implementing one-time-use authorization flows, like password reset links or email verification, where a self-contained, expirable token is a perfect fit.

It's the modern standard for representing claims securely, and understanding its strengths—and weaknesses—is non-negotiable for today's developer.

Go deeper

  • RFC 7519: The official specification for JSON Web Token (JWT). The source of truth.
  • jwt.io: A fantastic resource with a live debugger and list of libraries for nearly every language.
  • OWASP JWT Cheat Sheet: An essential guide to the security best practices and pitfalls of using JWTs (the advice is language-agnostic).
  • MDN Web Docs: Authorization header: Learn about the Bearer authentication scheme commonly used to transmit JWTs.
  • Wikipedia: JSON Web Token: A good high-level overview of the concept and its history.

Theory done. Time to get your hands dirty — 100% in your browser.

Try the tool: JWT Viewer