Session IDs and JWTs (JSON Web Tokens) are two common ways to implement authentication and session management in web applications. They solve the same problem—keeping users authenticated across multiple requests—but they do it differently.
Session ID (Server-side Sessions)
Concept
The server stores session data (e.g. user ID, login status) in memory or a database, and gives the client a session ID (usually in a cookie). The client sends this ID with each request, and the server uses it to retrieve the session data. So users don’t need to authenticate every time when they access a resource.
How it works:
- Login:
- User logs in.
- Server creates a session (
session_id -> {user_id: 123}) and stores it. - Server sends a session ID (e.g.,
abc123) back to the client in a cookie.
- Subsequent requests:
- Client automatically includes the cookie with
session_id=abc123. - Server looks up session by ID and checks if user is authenticated.
- If valid, server proceeds with the request.
- Client automatically includes the cookie with
- Logout / Expiry:
- Session can be destroyed on logout.
- Server can expire session after a timeout (e.g. 30 minutes of inactivity).
Pros
- Server has full control (can invalidate sessions at will).
- Easy to implement.
- Secure if HTTPS and secure cookies are used.
Cons
- Doesn’t scale well unless session store is shared (e.g. Redis) in distributed systems or microservices.
- Server needs to manage session lifecycle and storage.
CSRF risk
Using session ID authentication is vulnerable to CSRF (Cross-Site Request Forgery) attacks if not properly protected.
An attacker can trick the user (who is already authenticated) into making an unwanted request (e.g., a POST /transfer-funds) by embedding a form or script on a malicious site.
Because the browser sends the session cookie automatically, the server thinks it’s a legitimate request from the user.
Protect session ID auth from CSRF
- CSRF token
- CSRF is a random string generated on the server side and inject it into each from/page
- The client must include this token in
POST/PUT/DELETErequests - The server verifies that the CSRF token matches the expected one for that session
Protection using Spring Security
When CSRF protection is enabled (which it is by default for browser-based applications), Spring Security:
- Generates a random CSRF token per user session.
- Stores this token in the user’s
HttpSession. - Makes the token available to views (like JSP) or APIs (via an endpoint or custom filter).
JWT (JSON Web Token, Stateless Authentication)
Concept
JWT encodes session data (e.g., user ID, expiration) into a token and sends it to the client. The server doesn’t store sessions—it verifies tokens on each request.
Structure
JWT has a structure composed of three parts: a header, a payload, and a signature, all separated by period (.).
Header
The header contains metadata about the token, including the signing algorithm and token type here metadata means data about data.
{
"alg": "HS256",
"typ": "JWT"
}alg: Algorithm used for signing (e.g., HS256, RS256).typ: Token type, always “JWT”.
Base64Url Encoded Header
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Payload
The payload contains the information about the user also called as a claim and some additional information including the timestamp at which it was issued and the expiry time of the token.
{
"userId": 123,
"role": "admin",
"exp": 1672531199
}Common claim types:
iss(Issuer): Identifies who issued the token.sub(Subject): Represents the user or entity the token is about.aud(Audience): Specifies the intended recipient.exp(Expiration): Defines when the token expires.iat(Issued At): Timestamp when the token was created.nbf(Not Before): Specifies when the token becomes valid.
Base64Url Encoded Header
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNzA4MzQ1MTIzLCJleHAiOjE3MDgzNTUxMjN9
Signature
The signature ensures token integrity and is generated using the header, payload, and a secret key. In this example we will use HS256 algorithm to implement the Signature part. Base64Url Encoded Header
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Final JWT token
After all these steps the final JWT token is generated by joining the Header, Payload and Signature via a period. It looks like as it is shown below.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNzA4MzQ1MTIzLCJleHAiOjE3MDgzNTUxMjN9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
How it works:
- Login:
- User logs in.
- Server creates a JWT:
Example payload:header.payload.signature{ "user_id": 123, "exp": 1720835200 } - Server sends JWT to the client (usually via HTTP response or cookie).
- Subsequent requests:
- Client sends JWT (in header:
Authorization: Bearer <token>or in a cookie). - Server verifies signature and checks expiration.
- If valid, uses the embedded user info to process request.
- Client sends JWT (in header:
- Logout / Expiry:
- Server can’t revoke tokens (unless using a token blacklist).
- Tokens expire after a set time (e.g. 15 min, 1 hour).
Pros
- Stateless, no need to store anything on server. Good for microservices.
- Great for distributed / microservices architecture.
- Easy to pass around (e.g. mobile, APIs).
Cons
- Can’t easily revoke tokens unless you implement blacklists.
- If token is stolen, attacker is authenticated until token expires.
- Token size is larger than session ID.
Comparison Table
| Feature | Session ID | JWT |
|---|---|---|
| Storage | Server (e.g. memory, Redis) | Client (token stored) |
| Scalability | Harder, needs shared store | Easier, stateless |
| Revocation | Easy (delete session) | Hard (use blacklist) |
| Token size | Small (e.g. abc123) | Larger (contains data) |
| Security risk | Stolen ID = hijacked session | Stolen token = full access |
| Expiration control | Server-controlled | Token-controlled |
Summary
| Use This When… | Use Session ID | Use JWT |
|---|---|---|
| You need session invalidation | ✅ | ❌ unless you build it |
| You’re building a web app | ✅ Works well | ✅/❌ (depends on setup) |
| You’re building APIs / mobile | ❌ More complex | ✅ Ideal for API auth |
| You have a distributed system | ❌ Needs session replication | ✅ Stateless = better scalability |
Back to parent page: Web Security
Cyber_Security Web_Security Session JWT
Reference: