Information Security 8 min read

Combining JWT and Session for Secure and Scalable User Authentication

This article explains how JWT provides stateless authentication while Session adds an extra security layer and lifecycle management, and demonstrates their combined use with Java code to achieve both scalability and fine‑grained control over user sessions.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Combining JWT and Session for Secure and Scalable User Authentication

Using JWT for user authentication and authorization, with Session playing an auxiliary role, we discuss the functions of each in this combined model and why Session is needed.

JWT Role

User Authentication: JWT contains identity and permission information; the client sends the JWT with each request and the server validates it to confirm the user's identity.

Statelessness: JWT does not require server‑side storage of session data, allowing the server to be stateless, which facilitates scaling and load balancing.

Session Role

Additional Security Layer: Even though JWT is stateless, relying solely on it can pose security risks such as token leakage; Session provides an extra layer ensuring that a valid token must also have a corresponding server‑side session.

Token Lifecycle Management: Session makes it easier to manage token lifecycles, enabling forced re‑login, manual token revocation, and other operations.

"Remember Me" Control: When users select "Remember Me," Session records this state and, after JWT expiration, decides whether the old token may still be used.

Why Create a Session

Although JWT can be used in a stateless environment, introducing Session brings the following benefits:

Prevent Token Abuse: Server‑side Session verification ensures that even a valid token must be authenticated by the server, preventing malicious use.

Support User‑Initiated Logout: When a user logs out, the server can delete the Session record, making the token unusable even if it hasn't expired.

Fine‑Grained Control: Session enables detailed permission control and user state management, such as forced offline or session timeout handling.

State Tracking: In scenarios where tracking user activity, login history, etc., is necessary, Session provides the mechanism.

Advantages of Combining JWT and Session

Using both JWT and Session together leverages the strengths of each to balance security and scalability:

Stateless Authentication: JWT enables stateless authentication, facilitating horizontal scaling and load balancing.

State Management and Security: Session adds state management and an extra security layer, ensuring token usage is safe and reliable.

Code Example

Below is a simplified Java example showing how to create a JWT and a Session during user login:

public LoginResponse login(String username, String password) throws AuthException {
// Validate username and password
User user = userService.authenticate(username, password);
if (user == null) {
throw new AuthException("Invalid username or password");
}
// Generate JWT Token
String token = createJwt(user.getId(), user.getRoles());
// Create session
sessionManagerApi.createSession(token, user);
// Return token
return new LoginResponse(token);
}
public void createSession(String token, User user) {
LoginUser loginUser = new LoginUser();
loginUser.setToken(token);
loginUser.setUserId(user.getId());
loginUser.setRoles(user.getRoles());
sessionManagerApi.saveSession(token, loginUser);
}

During request validation, the JWT is first verified, then the corresponding Session is checked:

@Override
public DefaultJwtPayload validateToken(String token) throws AuthException {
try {
// 1. Validate JWT itself
JwtContext.me().validateTokenWithException(token);
// 2. Retrieve JWT payload
DefaultJwtPayload defaultPayload = JwtContext.me().getDefaultPayload(token);
// 3. If "remember me" is enabled, skip session check
if (defaultPayload.getRememberMe()) {
return defaultPayload;
}
// 4. Verify session contains this token
LoginUser session = sessionManagerApi.getSession(token);
if (session == null) {
throw new AuthException(AUTH_EXPIRED_ERROR);
}
return defaultPayload;
} catch (JwtException jwtException) {
if (JwtExceptionEnum.JWT_EXPIRED_ERROR.getErrorCode().equals(jwtException.getErrorCode())) {
throw new AuthException(AUTH_EXPIRED_ERROR);
} else {
throw new AuthException(TOKEN_PARSE_ERROR);
}
} catch (io.jsonwebtoken.JwtException jwtSelfException) {
throw new AuthException(TOKEN_PARSE_ERROR);
}
}

Conclusion

In this scenario, JWT provides stateless user authentication for convenience and scalability, while Session acts as an auxiliary mechanism offering additional security and state management. Combining the two allows a system to be highly extensible while maintaining fine‑grained security controls.

JavaSecurityAuthenticationJWTStatelesssession
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.