A practical, in-depth guide to JSON Web Tokens — how they are structured, how signatures are verified, and how to use them securely in real systems.
Imagine you hold a membership card (the JWT) that grants you access to an exclusive club (the protected resource or API).
You show your ID card (username and password) to the club's front desk (the authentication server). Once the front desk verifies who you are, it issues you a special membership card (the JWT). The card carries your basic details (name, membership tier) and bears the club manager's tamper-proof signature (the digital signature).
You walk up to the bar area (an API endpoint) with your membership card to order a drink. The security guard (the API server) does not need to phone the front desk to ask who you are. He only needs to:
iss issuer)exp) to confirm it has not expiredKey takeaway: the guard (API server) can validate the card entirely on his own, without calling the front desk (authentication server) or querying its database on every request. That is the core advantage of JWT: it is stateless and can be verified in a distributed way.
JWT (JSON Web Token) is an open standard (RFC 7519) that defines a compact and self-contained way to securely transmit information between parties as a JSON object.
Compact: it is small enough to be sent through a URL, a POST parameter or an HTTP header (Authorization).
Self-contained: the payload carries all the information the consumer needs about the user, avoiding repeated database lookups.
A JWT looks like this (three parts separated by dots):
xxxxx.yyyyy.zzzzz
A real example:
Header: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Payload: eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
Signature: SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
A JWT is made of three parts: the Header, the Payload and the Signature.
The header typically consists of two fields: the token type (JWT) and the signing algorithm being used (such as HMAC SHA256 or RSA).
{ "alg": "HS256", "typ": "JWT" }
This JSON object is Base64Url-encoded to form the first part of the JWT.
The payload contains the claims. Claims are statements about an entity (typically the user) plus any additional data.
{ "sub": "1234567890", "name": "John Doe", "admin": true, "iat": 1516239022 }
There are three types of claims:
iss (issuer), exp (expiration time) and sub (subject)Important
The payload is only encoded, not encrypted. Anyone who obtains the JWT can decode and read its contents. Never put sensitive information (such as passwords) in the payload.
This is the most critical, security-bearing part of a JWT. The signature proves the message has not been tampered with along the way.
With a symmetric algorithm, the signature is computed like this:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret )
In production, tokens are usually issued with a safer asymmetric algorithm (such as RS256) instead of a symmetric one (HS256). This introduces the concepts of a public key and a private key:
Using JWT involves two main flows: issuing the token and verifying it. The client signs in with a username and password against the authentication service; after the user's identity is confirmed, the service issues a token to the client, and the client then presents that token when calling business APIs. The complete flow looks like this:
1. Client signs in and obtains a token
Client ── login request (username + password) ──▶ Auth service
Auth service: verify credentials → generate token
Auth service ── returns the JWT ──▶ Client
2. Client calls protected business APIs with the token
Client ── business API call (carrying the JWT) ──▶ API gateway
API gateway: verify the token (signature / exp / iss / roles)
API gateway ──▶ Business service ── response ──▶ API gateway ──▶ Client
After the client sends a login request and the authentication service validates the username and password, the service builds the JWT header and payload, signs them with its private key using the chosen algorithm (such as RS256), assembles the three parts into the complete JWT and returns it to the client.
The client stores the received JWT locally (in localStorage or a cookie). On subsequent requests to protected APIs, the client sends the JWT in the HTTP Authorization header using the format Authorization: Bearer token. When the request reaches the API gateway, the gateway parses the token and validates it with the public key, mainly along these dimensions:
exp timestampiss claimKey advantage: the API server (resource server) never needs to reach the authentication server or a database. It completes every validation step on its own — this is the essence of JWT's stateless, distributed verification model.
Now that you understand how JWT works, put that knowledge into practice with our free tools:
Suggested exercise: first create a JWT with the JWT Generator, then paste it into JWT Decode to parse and verify it. Walking through the full token lifecycle is the fastest way to internalize the concepts.