Expand Authors Top

If you have a few years of experience in the Java ecosystem and you’d like to share that with the community, have a look at our Contribution Guidelines.

Expanded Audience – Frontegg – Security (partner)
announcement - icon User management is very complex, when implemented properly. No surprise here.

Not having to roll all of that out manually, but instead integrating a mature, fully-fledged solution - yeah, that makes a lot of sense.
That's basically what Frontegg is - User Management for your application. It's focused on making your app scalable, secure and enjoyable for your users.
From signup to authentication, it supports simple scenarios all the way to complex and custom application logic.

Have a look:

>> Elegant User Management, Tailor-made for B2B SaaS

NPI – Security Top – Temp – Non-Geo (Frontegg)

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
NPI – Frontegg – Security – (partner)
announcement - icon User management is very complex, when implemented properly. No surprise here.

Not having to roll all of that out manually, but instead integrating a mature, fully-fledged solution - yeah, that makes a lot of sense.
That's basically what Frontegg is - User Management for your application. It's focused on making your app scalable, secure and enjoyable for your users.
From signup to authentication, it supports simple scenarios all the way to complex and custom application logic.

Have a look:

>> Elegant User Management, Tailor-made for B2B SaaS

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 {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
          .logout(logout -> logout
            .logoutUrl("/basic/basiclogout")
            .addLogoutHandler(new SecurityContextLogoutHandler())
          );
        return http.build();
    }
}

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

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

To do that, we can create our own LogoutHandler that loops through all cookies and expires them on logout:

@Configuration
public class AllCookieClearingLogoutConfiguration {
    @Bean
    public SecurityFilterChain filterChain(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);
                }
            })
          );
        return http.build();
    }
}

In fact, Spring Security provides CookieClearingLogoutHandler which is a ready-to-use logout handler for cookie removal.

4. Clear-Site-Data Header Logout

Likewise, we can use a special HTTP response header to achieve the same thing; this is where the Clear-Site-Data header comes into play.

Basically, the Clear-Data-Site header clears browsing data (cookies, storage, cache) associated with the requesting website:

@Configuration
public class ClearSiteDataHeaderLogoutConfiguration {

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

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
          .logout(logout -> logout
            .logoutUrl("/csd/csdlogout")
            .addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(SOURCE)))
          );
        return http.build();
    }
}

However, 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. Logout on Request

Similarly, we can use HttpServletRequest.logout() method to log a user out.

Firstly, let's add the necessary configuration to manually call logout() on the request:

@Configuration
public static class LogoutOnRequestConfiguration {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.antMatcher("/request/**")
            .authorizeRequests(authz -> authz.anyRequest()
                .permitAll())
            .logout(logout -> logout.logoutUrl("/request/logout")
                .addLogoutHandler((request, response, auth) -> {
                    try {
                        request.logout();
                    } catch (ServletException e) {
                        logger.error(e.getMessage());
                    }
                }));
        return http.build();
    }
}

Finally, let's create a test case to confirm that everything works as expected:

@Test
public void givenLoggedUserWhenUserLogoutOnRequestThenSessionCleared() throws Exception {

    this.mockMvc.perform(post("/request/logout").secure(true)
        .with(csrf()))
        .andExpect(status().is3xxRedirection())
        .andExpect(unauthenticated())
        .andReturn();
}

6. Conclusion

In summary, 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
Security footer banner
Comments are closed on this article!