Introduction
Imagine you arrive at a hotel.
At the reception, you show your ID and prove who you are. The receptionist then gives you a room key card.
You don't need to show your ID every time you enter your room. Instead, you simply present the key card.
The hotel doesn't need to ask your name again because the card itself proves that you already authenticated.
JWT (JSON Web Token) works exactly like that.
- Username and password = Your ID
- JWT = Hotel key card
- Server = Receptionist
What is JWT?
JWT stands for JSON Web Token.
It is a compact string that proves a user has already logged in successfully.
Instead of storing login sessions on the server, the server gives the client a signed token.
The client sends this token with every request.
Example:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
The server verifies the token and allows access.
Why Do We Need JWT?
Without JWT, every request would require sending the username and password repeatedly.
Browser
|
Username
Password
|
Server
That would be inefficient and insecure.
Instead:
Login once
↓
Receive JWT
↓
Reuse JWT for every request
Stateless Authentication
JWT enables stateless authentication.
Stateful Authentication
Server
|
|-- Session #12345
|-- Session #91821
|-- Session #44211
The server stores every user's session.
Stateless Authentication (JWT)
Server
(No session storage)
↓
Only verifies token signature
The server doesn't remember users.
The token remembers.
JWT Structure
A JWT consists of three parts separated by periods.
Header.Payload.Signature
Example
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJzdWIiOiIxMjMiLCJuYW1lIjoiRXZhbnMiLCJyb2xlIjoiYWRtaW4ifQ
.
K6L6GQX....
Think of it like
Envelope
Letter
Wax Seal
Part 1 — Header
Example
{
"alg": "HS256",
"typ": "JWT"
}
The header tells us:
- Which algorithm signed the token.
- What type of token it is.
Fields:
-
alg→ Signing algorithm -
typ→ JWT
Common algorithms:
- HS256
- RS256
- ES256
Part 2 — Payload
The payload contains claims.
Example:
{
"user_id": 42,
"name": "Evans",
"role": "admin"
}
Think of it as your digital identity card.
Typical information:
- User ID
- Username
- Role
- Permissions
Standard Claims
| Claim | Meaning |
|---|---|
| sub | Subject (User ID) |
| exp | Expiration Time |
| iat | Issued At |
| iss | Issuer |
| aud | Audience |
Example
{
"sub":"42",
"role":"admin",
"exp":1754440000
}
Important
The payload is NOT encrypted.
Anyone can decode it.
JWT
↓
Base64URL Decode
↓
Payload
Never store:
- Passwords
- PINs
- Secret Keys
- API Keys
- Credit Card Numbers
inside a JWT.
Part 3 — Signature
The signature protects the token from tampering.
The server computes something similar to:
HMACSHA256(
Base64(Header)
+
Base64(Payload),
SecretKey
)
This produces the signature.
The secret key never leaves the server.
Why the Signature Matters
Suppose someone changes:
{
"role":"user"
}
to
{
"role":"admin"
}
The payload changes.
Therefore the signature changes.
Since the attacker doesn't know the server's secret key, they cannot generate a valid signature.
Result:
Server
↓
Verify Signature
↓
Invalid
↓
401 Unauthorized
This is why JWTs are tamper-evident.
Login Flow
User
↓
POST /login
↓
Username
Password
↓
Server
Server:
- Checks the database.
- Verifies the password.
- Generates a JWT.
- Returns it.
Example response:
{
"token":"eyJhbGc..."
}
The client stores the token.
Authenticated Request
GET /profile
Authorization: Bearer eyJhbGc...
Server:
- Reads the Authorization header.
- Verifies the signature.
- Checks expiration.
- Extracts the user ID.
- Returns the requested resource.
Complete Request Lifecycle
Client
↓
Login
↓
Receive JWT
↓
Store JWT
↓
Send JWT
↓
Server verifies
↓
Access granted
Where Should Tokens Be Stored?
Browser
Preferred:
- Secure HttpOnly Cookies
- Memory (for SPAs)
Avoid storing long-lived access tokens in localStorage because XSS attacks can expose them.
Mobile
Use secure platform storage:
- iOS Keychain
- Android Keystore
Token Expiration
Example
{
"exp":1754440000
}
Server checks:
Current Time
↓
Expired?
↓
Yes
↓
401 Unauthorized
Expired tokens cannot be used.
Refresh Tokens
Access tokens should have short lifetimes.
Example:
Access Token
15 Minutes
When expired:
Client
↓
Refresh Token
↓
Server
↓
New Access Token
Refresh tokens allow users to remain logged in without entering credentials repeatedly.
JWT vs Sessions
| JWT | Sessions |
|---|---|
| Stateless | Stateful |
| No server-side session storage | Server stores sessions |
| Easy to scale | More difficult to scale |
| Great for APIs | Great for traditional web applications |
| Client sends token | Client sends session cookie |
JWT in a Go (Gin) Backend
Login Endpoint
POST /login
↓
Validate Request
↓
Find User
↓
Compare Password Hash
↓
Generate JWT
↓
Return Token
Protected Route
GET /users
↓
JWT Middleware
↓
Read Authorization Header
↓
Verify Signature
↓
Check Expiration
↓
Extract Claims
↓
Next()
↓
Handler Executes
Middleware Flow
Incoming Request
│
▼
Read Authorization Header
│
▼
Token Present?
│ │
No Yes
│ ▼
401 Verify Signature
│
Valid? │
│ │
No Yes
│ ▼
401 Check Expiration
│
Expired? │
│ │
Yes No
│ ▼
401 Extract Claims
│
▼
Store User in Context
│
▼
Execute Next Handler
Authentication vs Authorization
Authentication answers:
Who are you?
Authorization answers:
What are you allowed to do?
Example:
Login
↓
Authentication
↓
JWT
↓
Authorization
↓
Access Granted
Common Interview Questions
What is JWT?
A signed JSON token used for stateless authentication.
Is JWT encrypted?
No.
It is Base64URL encoded and digitally signed, but not encrypted.
Why can't users modify the payload?
Because changing the payload invalidates the signature.
What is the purpose of the signature?
To guarantee integrity and authenticity.
Why does JWT expire?
To reduce the damage if a token is stolen.
What is a Refresh Token?
A long-lived credential used to request a new access token after the current one expires.
What happens if the signature is invalid?
The server rejects the request with 401 Unauthorized.
Why is JWT called stateless?
Because the server does not store user sessions.
Every request contains all the information needed to authenticate the user.
Best Practices
- Always use HTTPS.
- Never store passwords inside JWTs.
- Keep access tokens short-lived (10–30 minutes).
- Use refresh tokens for long-lived sessions.
- Store refresh tokens securely.
- Validate the signature on every request.
- Validate the expiration (
exp) claim. - Use strong signing algorithms.
- Rotate signing keys when appropriate.
- Implement token revocation if your application requires immediate logout or compromised-token handling.
Key Takeaways
- JWT stands for JSON Web Token.
- A JWT has three parts:
- Header
- Payload
- Signature
- The payload is readable by anyone who has the token.
- The signature protects against tampering.
- JWT enables stateless authentication.
- Access tokens should expire.
- Refresh tokens provide a secure way to obtain new access tokens.
- JWT authentication is commonly implemented using middleware in Go (Gin), Express.js, Spring Boot, ASP.NET, and many other backend frameworks.
Final Mental Model
Think of JWT like a hotel key card.
User
│
│ Login (Username + Password)
▼
Server verifies credentials
│
▼
Issues a signed JWT
│
▼
Client stores the token
│
▼
Client sends the token with every request
│
▼
Server verifies:
✔ Signature
✔ Expiration
✔ Claims
│
▼
Access Granted
The server does not need to remember the user.
The signed token carries the identity, while the server only needs its secret (or public key, depending on the algorithm) to verify that the token is authentic and has not been altered.
Top comments (0)