Logout Handling
About
Logout Handling in Spring Security is the process of terminating an authenticated session, ensuring the user is properly logged out and any session data is cleared.
Why is Logout Handling Important?
Security – Prevent unauthorized access after a user logs out.
Session Cleanup – Remove authentication details from memory.
Token Revocation – Ensure JWT or API tokens are invalidated.
How Logout Works in Spring Security?
Spring Security provides built-in logout support that:
Invalidates HTTP session (if using session-based authentication).
Clears SecurityContext (removes authentication details).
Deletes Remember-Me cookies (if enabled).
Redirects users after logout (configurable).
Default Logout Handling in Spring Security
By default, Spring Security enables logout via a GET or POST request to /logout
.
For session-based authentication, it invalidates the session.
For JWT or API tokens, additional custom logic is needed.
Implementing Logout in Spring Security
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
)
.formLogin(withDefaults()) // Enables login
.logout(logout -> logout // Enables logout
.logoutUrl("/logout") // Custom logout URL
.logoutSuccessUrl("/login?logout") // Redirect after logout
.invalidateHttpSession(true) // Invalidate session
.deleteCookies("JSESSIONID") // Remove cookies
);
return http.build();
}
}
logoutUrl("/logout")
→ Defines the logout endpoint.logoutSuccessUrl("/login?logout")
→ Redirects users after logout.invalidateHttpSession(true)
→ Destroys the session.deleteCookies("JSESSIONID")
→ Removes session cookies.
Custom Logout Handler
If we need custom logic (e.g., logging, token revocation, auditing), implement a LogoutHandler.
Step 1: Create a Custom Logout Handler
@Component
public class CustomLogoutHandler implements LogoutHandler {
@Override
public void logout(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) {
if (authentication != null) {
System.out.println("User " + authentication.getName() + " is logging out.");
}
request.getSession().invalidate(); // Invalidate session
}
}
logout()
method executes custom logic (e.g., logging, API calls).Can be used to log logout events or notify external services.
Step 2: Register the Custom Logout Handler
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Autowired
private CustomLogoutHandler customLogoutHandler;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
)
.logout(logout -> logout
.addLogoutHandler(customLogoutHandler) // Register custom logout handler
.logoutSuccessUrl("/login?logout")
);
return http.build();
}
}
Logout in JWT-Based Authentication
In JWT-based authentication, logout does not rely on session invalidation. Instead, we:
Blacklist JWTs (store invalid tokens in a database or cache).
Use short-lived tokens with refresh tokens.
Clear tokens from client-side storage (e.g., local storage or cookies).
Custom JWT Logout Handler
@Component
public class JwtLogoutHandler implements LogoutHandler {
@Autowired
private TokenBlacklistService tokenBlacklistService; // Custom service to blacklist JWT
@Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
String token = extractToken(request);
if (token != null) {
tokenBlacklistService.blacklistToken(token); // Add token to blacklist
}
}
private String extractToken(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
return (bearerToken != null && bearerToken.startsWith("Bearer ")) ?
bearerToken.substring(7) : null;
}
}
Extracts JWT token from Authorization header.
Adds token to a blacklist (Redis, database, etc.).
Register JWT Logout Handler
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
)
.logout(logout -> logout
.addLogoutHandler(new JwtLogoutHandler())
.logoutSuccessHandler((request, response, authentication) -> {
response.setStatus(HttpServletResponse.SC_OK);
})
);
return http.build();
}
logoutSuccessHandler()
sends a200 OK
response instead of redirecting.
Logout in OAuth2 Authentication
In OAuth2-based authentication, logging out means:
Clearing the local session.
Revoking the OAuth2 access token (if supported by provider).
@Component
public class OAuth2LogoutHandler implements LogoutHandler {
@Autowired
private OAuth2AuthorizedClientService clientService;
@Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
if (authentication instanceof OAuth2AuthenticationToken) {
OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication;
clientService.removeAuthorizedClient(oauthToken.getAuthorizedClientRegistrationId(), oauthToken.getName());
}
}
}
Removes OAuth2 tokens from the client store.
Custom Logout Success Handler
If we need to perform custom logic after logout, implement LogoutSuccessHandler
.
@Component
public class CustomLogoutSuccessHandler implements LogoutSuccessHandler {
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException {
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().write("Logout Successful!");
}
}
Sends a custom response instead of a redirect.
Register Logout Success Handler
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.logout(logout -> logout
.logoutUrl("/logout")
.logoutSuccessHandler(new CustomLogoutSuccessHandler())
);
return http.build();
}
Security Considerations for Logout Handling
Risk
Mitigation
Session Hijacking
Ensure session invalidation on logout.
Token Replay Attacks
Implement JWT blacklisting.
CSRF Attacks on Logout
Use POST-only logout requests.
Last updated
Was this helpful?