How Session and Token Authentication Work (with Spring Security Examples)

Share this

Authentication is foundational to every application, but the way we implement it has evolved significantly. For years, session-based authentication (using cookies and server-side state) was the default. Today, token-based authentication, powered by standards like OAuth 2.0 and JWTs, dominates modern API architectures.
Note: This article belongs to Part 1.2: Identity & Access Management in our Application Security series.

Have you ever wandered about Stateless vs Stateful Authentication: When to Use Tokens Over Sessions? In this article, we’ll explore both models in depth, contrast their trade-offs, and walk through implementation examples using Spring Security.

Session-Based Authentication: The Traditional Model

🔍 What It Is

In session-based authentication, a user logs in with credentials. The server validates them and creates a session, storing session data (like the user’s ID) on the server. A session ID is then sent to the client in a cookie.

⚙️ How It Works

  1. User logs in via form → server creates a session (HttpSession)
  2. Server stores user info (e.g., in-memory, Redis, database)
  3. Client gets a cookie with a session ID (JSESSIONID)
  4. On each request, the browser automatically sends the cookie
  5. The server uses the session ID to look up the user

✅ Spring Security: Session-Based Auth Configuration

@Configuration
@EnableWebSecurity
public class SecurityConfig {

@Bean
public SecurityFilterChain sessionBasedSecurity(HttpSecurity http) throws Exception {
http
.formLogin() // Enables traditional login page
.and()
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
)
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED); // default behavior

return http.build();
}
}

Spring automatically manages the session lifecycle and stores the user in SecurityContext.

✔️ Pros

  • Simpler for web apps (especially monoliths)
  • Built-in CSRF protection using same-origin cookies
  • Transparent to developers — sessions are managed by framework

❌ Cons

  • Doesn’t scale well in distributed systems without session replication
  • Requires sticky sessions or centralized session stores (e.g., Redis)
  • Not ideal for mobile or single-page apps (SPA) that rely on APIs
  • Poor fit for stateless REST APIs
Application Security Series 1
Application Security Series 1

Token-Based Authentication: The Modern Approach

🔍 What It Is

Token-based authentication issues a self-contained token (e.g., JWT) after login. The server does not store any session data. Instead, the token includes all necessary user claims and is sent with every request (usually in an Authorization header).

⚙️ How It Works

  1. User logs in (e.g., via OAuth2/OIDC)
  2. Server or IdP issues an access token (JWT)
  3. Client stores the token (in memory or localStorage)
  4. Client includes token in each API request:
    Authorization: Bearer <token>
  5. Backend verifies the token and grants access

✅ Spring Security: Token-Based (Stateless) Auth

@Configuration
public class ResourceServerConfig {

@Bean
public SecurityFilterChain tokenSecurity(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2
.jwt() // Enables JWT validation
)
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS); // crucial for token auth

return http.build();
}
}

Spring will decode the JWT and extract claims automatically. You can inject them using @AuthenticationPrincipal or access via SecurityContextHolder.

✔️ Pros

  • Stateless — no need for server-side session storage
  • Scales easily in distributed and microservices architectures
  • Works across web, mobile, CLI, and IoT clients
  • Ideal for API-first or decoupled frontend-backend applications

❌ Cons

  • Requires secure storage of tokens on the client
  • No built-in invalidation (logout can be hard to enforce without token revocation)
  • More complex to secure (token expiration, refresh flow, replay protection)

Technical Comparison: Session vs Token Auth

FeatureSession-BasedToken-Based (e.g., JWT)
StorageServer (session store)Client-side (localStorage, memory)
TransportCookie (JSESSIONID)Header (Authorization: Bearer)
Stateless❌ No✅ Yes
ScalabilityRequires sticky sessions or shared storeScales naturally across services
Token FormatSession ID (opaque)JWT (self-contained)
RevocationEasy (server-side)Complex (need blacklist or short TTL)
CSRF RiskHigh (requires CSRF tokens)Low (tokens in headers are not auto-sent)
Spring SupportformLogin(), session managementoauth2ResourceServer(), jwt()

When to Use Which

Use CaseRecommended Approach
Traditional web app (monolith)✅ Session-based auth
SPA with REST APIs✅ Token-based auth
Mobile applications✅ Token-based auth
Microservices with shared identity✅ Token-based auth
Admin panel on intranet✅ Session-based auth

Common Mistakes to Avoid

  • ❌ Using sessions in a microservices environment without sticky sessions
  • ❌ Storing JWTs in localStorage (consider XSS risks)
  • ❌ Not setting sessionCreationPolicy(STATELESS) when using tokens
  • ❌ Confusing id_token (OIDC) with access_token (OAuth2)

Security Best Practices

  • Use HTTPS exclusively for both models
  • Store tokens securely — prefer in-memory over localStorage if possible
  • Use short-lived access tokens + refresh tokens
  • Protect against CSRF (with session-based auth) and XSS (with token-based auth)
  • Rotate keys for signing JWTs regularly

Conclusion

The choice between session-based and token-based authentication depends on your application’s architecture, client types, and scalability requirements.

  • Session-based authentication remains appropriate for traditional web apps and internal tools.
  • Token-based authentication is the de facto standard for modern, distributed, API-driven systems.

Spring Security supports both models with robust, configurable patterns. By understanding their differences and trade-offs, developers can make informed decisions that balance user experience, security, and scalability.

Check out https://en.wikipedia.org/wiki/Access_token and https://en.wikipedia.org/wiki/JSON_Web_Token Wikipedia links for more information on the current topic.

What’s Next

Up Next in our Application Security Series is:
Part 2.1 👉 OAuth 2.0 Deep Dive: A Guide to Tokens, Flows & Delegate Access with Spring Security

We’ll explore the OAuth 2.0 concepts:

  • Authorization flows (Authorization Code, Client Credentials, etc.)
  • Access tokens vs refresh tokens
  • How OAuth enables delegated access

We’ll also look at how these flows are implemented using Spring Security’s @EnableOAuth2Client, @EnableAuthorizationServer, and oauth2Login().

Have a Question?

Have implementation questions about Spring Security or architecture concerns around auth? Drop them in the comments — I’d love to hear how you’re applying these patterns in your own stack.

Share this

Leave a comment

Your email address will not be published. Required fields are marked *