Cookies, Sessions, Tokens, JWT & OAuth2: Choosing the Right Secure Authentication Method
This article explains the differences, technical details, and best‑practice implementations of Cookies, Sessions, Tokens, JWT and OAuth 2.0, helping developers decide which authentication mechanism fits various web and API scenarios while addressing security considerations.
1. Cookie: HTTP’s identity card
Cookie is a small piece of text stored in the browser, set by the server via the Set-Cookie header and sent back in subsequent requests via the Cookie header.
Cookie attributes
Attribute
Effect
Security advice
HttpOnly
Prevents JavaScript access
Must be true to prevent XSS
Secure
Sent only over HTTPS
Enable in production
SameSite
Controls cross‑site sending
Set to Strict or Lax
Max-Age
Cookie lifetime
Adjust per security requirements
// Server sets Cookie
@PostMapping("/login")
public ResponseEntity login(@RequestBody User user, HttpServletResponse response) {
if (authService.authenticate(user)) {
Cookie cookie = new Cookie("session_id", generateSessionId());
cookie.setMaxAge(3600); // 1 hour
cookie.setHttpOnly(true);
cookie.setSecure(true);
cookie.setPath("/");
response.addCookie(cookie);
return ResponseEntity.ok().build();
}
return ResponseEntity.status(401).build();
}
// Read Cookie
@GetMapping("/profile")
public ResponseEntity getProfile(@CookieValue("session_id") String sessionId) {
User user = sessionService.getUserBySession(sessionId);
return ResponseEntity.ok(user);
}2. Session: Server‑side user profile
Session stores user state on the server. The server creates a unique Session ID and sends it to the browser via a Cookie; subsequent requests include the ID, allowing the server to identify the user.
public class UserSession {
private String sessionId;
private String userId;
private String username;
private Date loginTime;
private Date lastAccessTime;
private Map<String, Object> attributes;
}Typical storage options include in‑memory (default) and Redis for distributed environments.
# application.yml
server:
servlet:
session:
timeout: 1800 # 30 minutes @Configuration
@EnableRedisHttpSession
public class SessionConfig {
@Bean
public LettuceConnectionFactory connectionFactory() {
return new LettuceConnectionFactory();
}
}3. Token: Decentralized credential
A token is a self‑contained credential that carries all necessary information, so the server does not need to keep session state.
public String generateToken(User user) {
long now = System.currentTimeMillis();
return JWT.create()
.withIssuer("myapp")
.withSubject(user.getId())
.withClaim("username", user.getUsername())
.withClaim("role", user.getRole())
.withIssuedAt(new Date(now))
.withExpiresAt(new Date(now + 3600000))
.sign(Algorithm.HMAC256(secret));
}
public boolean validateToken(String token) {
try {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret))
.withIssuer("myapp")
.build();
verifier.verify(token);
return true;
} catch (JWTVerificationException e) {
return false;
}
}4. JWT: Standardized token
JWT (JSON Web Token) is an open standard (RFC 7519) for securely transmitting JSON data. Its structure is header.payload.signature.
// Header
{
"alg": "HS256",
"typ": "JWT"
}
// Payload
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"exp": 1516242622
} public String createJWT(User user) {
return Jwts.builder()
.setHeaderParam("typ", "JWT")
.setSubject(user.getId())
.setIssuer("myapp")
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 3600000))
.claim("username", user.getUsername())
.claim("role", user.getRole())
.signWith(SignatureAlgorithm.HS256, secret.getBytes())
.compact();
}5. OAuth 2.0: Authorization framework
OAuth 2.0 enables third‑party applications to access protected resources on behalf of a user after obtaining consent. Main roles are Resource Owner, Client, Authorization Server, and Resource Server.
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("clientapp")
.secret(passwordEncoder.encode("123456"))
.authorizedGrantTypes("authorization_code", "refresh_token")
.scopes("read", "write")
.redirectUris("http://localhost:8080/callback");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore())
.accessTokenConverter(accessTokenConverter());
}
}6. Comparison of concepts
Concept
Nature
Storage
Main use
Key traits
Cookie
HTTP state mechanism
Browser
Maintain session
Auto‑sent, size‑limited
Session
Server‑side state
Server
Store user state
Requires storage management
Token
Access credential
Client/Server
Authentication
Self‑contained, verifiable
JWT
Token standard
Client/Server
Secure data transfer
Standardized, signed
OAuth2
Authorization framework
None (delegates)
Third‑party access
Standard flow
7. Recommendations
Simple web apps: Session + Cookie
SPA / API backends: JWT in HTTP header
Third‑party login: OAuth 2.0 + JWT
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
