1. Introduction

Spring Security is the standard for securing Spring-based applications. It has several features to manage user's authentication, including login and logout. 

In this tutorial, we'll focus on manual logout with Spring Security.

We'll assume that readers already understand the standard Spring Security logout process.

2. Basic Logout

When a user attempts a logout, it has several consequences on its current session state. We need to destroy the session with two steps:

  1. Invalidate HTTP session information.
  2. Clear SecurityContext as it contains authentication information.

Those two actions are performed by the SecurityContextLogoutHandler.

Let's see that in action:

@Configuration
public class DefaultLogoutConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
          .logout(logout -> logout
            .logoutUrl("/basic/basiclogout")
            .addLogoutHandler(new SecurityContextLogoutHandler())
          );
    }
}

Note that SecurityContextLogoutHandler is added by Spring Security by default – we just show it here for clarity.

3. Cookie Clearing Logout

Often, a logout also requires us to clear some or all of a user's cookies.

We can create our own LogoutHandler that loops through all cookies and expires them on logout:

@Configuration
public class AllCookieClearingLogoutConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
          .logout(logout -> logout
            .logoutUrl("/cookies/cookielogout")
            .addLogoutHandler((request, response, auth) -> {
                for (Cookie cookie : request.getCookies()) {
                    String cookieName = cookie.getName();
                    Cookie cookieToDelete = new Cookie(cookieName, null);
                    cookieToDelete.setMaxAge(0);
                    response.addCookie(cookieToDelete);
                }
            })
          );
    }
}

On the other hand, Spring Security provides CookieClearingLogoutHandler which is a ready-to-use logout handler for cookie removal.

4. Clear-Site-Data Header Logout

Alternatively, we can use a special HTTP response header to achieve the same thing; this is where the Clear-Site-Data header comes into play. The Clear-Data-Site header clears browsing data (cookies, storage, cache) associated with the requesting website:

@Configuration
public class ClearSiteDataHeaderLogoutConfiguration extends WebSecurityConfigurerAdapter {

    private static final ClearSiteDataHeaderWriter.Directive[] SOURCE = 
      {CACHE, COOKIES, STORAGE, EXECUTION_CONTEXTS};

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
          .logout(logout -> logout
            .logoutUrl("/csd/csdlogout")
            .addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(SOURCE)))
          );
    }
}

Note that storage cleansing might corrupt the application state when we clear only one type of storage. Therefore, due to Incomplete Clearing, the header is only applied if the request is secure.

5. Conclusion

Spring Security has many built-in features to handle authentication scenarios. It always comes in handy to master how to use those features programmatically.

As always, the code for these examples is available over on GitHub.

Security bottom

I just announced the new Learn Spring Security course, including the full material focused on the new OAuth2 stack in Spring Security 5:

>> CHECK OUT THE COURSE
Comments are closed on this article!