Spring Security Logout

In the last article, we learned how to create login using spring security. In this article, we will learn how to perform spring security logout. Spring security provides a build in capabilities to handle most of the complex tasks during the logout.

Spring Security Logout

Logout id an integral part of any secure application. Logout ensure that all sensitive information is removed or invalidated once customer performs the logout. Spring security store authentication information in the session. Spring security automatically handles the following tasks for the application.

  1. Invalidating the HTTP Session.
  2. Cleaning up any RememberMe authentication configuration.
  3. Clearing the SecurityContextHolder.
  4. Redirect user to the configured page.

In this post, we will inspect the logout functionality using spring security and spring boot along with the extension points.

1. Application Setup

Let’s start by creating a sample application. You can also download the complete application from our GitHub repository. If needed, you can use IDE or Spring initializr to create the application. We are adding the following dependencies for our application by utilizing Spring boot auto configuration feature.

  1. Spring security auto configuration.
  2. Spring web starter.
  3. Thymeleaf.

This is how the pom.xml look like:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.3.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.javadevjoural</groupId>
	<artifactId>spring-security-logout</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>Spring Security Logout</name>
	<description>Spring Security Logout</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins&gt;
	</build>
</project>
Activate a New Account via Email Using Spring Security

2. Logout Configuration

Since Spring security will handle most of the heavy lifting during the logout process, we only need to configure few details our custom security configuration class extending the WebSecurityConfigurerAdapter. Here is the basic configuration to enable the logout feature:

protected void configure(HttpSecurity http) throws Exception {
    http
        .logout(logout -> logout                                                                              
        );
}

There are few things which we should keep in mind when enabling the logout feature:

  1. On successful logout, customer by default redirected to the /login?logout. Spring security provides flexibility to change the URL.
  2. If CSRF protection is active (default), Spring security expects the logout request must of POST type, we can use the GET logout request by disabling the CSRF protection.

Here is the complete reference in case you need more control on the logout process:

protected void configure(HttpSecurity http) throws Exception {
    http
        .logout(logout -> logout                                                
            .logoutUrl("/my/logout")                                            
            .logoutSuccessUrl("/home")                                      
            .logoutSuccessHandler(logoutSuccessHandler)                         
            .invalidateHttpSession(true)                                        
            .addLogoutHandler(logoutHandler)                                    
            .deleteCookies(cookieNamesToClear)                                  
        )
}
  • logoutSuccessURL – help to redirect the user to a landing page post logout, the default The default is /login?logout (In our case, we are redirecting to the home page).
  • logoutSuccessHandler – Handler, which triggers once the logout is complete. We can use this to handle redirection or forwarding to the destination.Keep in mind that the logoutSuccessUrl() will be ignored if we configure the logoutSuccessHandler.
  • invalidateHttpSession – Controls if HTTP session should be invalided. The default value is true.
  • deleteCookies – Delete any secure cookies (in case we are setting during the login.)

To customize logout functionality, you can add <a href="https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/web/authentication/logout/LogoutHandler.html" target="_blank" rel="noopener noreferrer">LogoutHandler</a> and/or <a title="LogoutSuccessHandler" href="https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/web/authentication/logout/LogoutSuccessHandler.html" target="_blank" rel="noopener noreferrer">LogoutSuccessHandler</a> implementations.

3. Spring Security Logout UI

We need to give the option to the customer to click on the logout link. Spring security provides following 2 options:

  1. Perform the POST logout (this is default and recommended.)
  2. Perform the GET logout by disabling CSRF feature.

We are using the Thymeleaf as the templating engine, please change the code as per your UI.

<div sec:authorize="isAuthenticated()">
    <a href="javascript: document.logoutForm.submit()" class="dropdown-toggle">Sign out</a>
    <form name="logoutForm" th:action="@{/logout}" method="post" th:hidden="true">
        <input hidden type="submit" value="Sign Out" />
    </form>
</div>

We are doing a POST logout request. Also remember following:

  1. Your request for action should be /logout. This is the logout handler from Spring security.

We are using sec:authorize="isAuthenticated()

To ensure that logout link is only visible to the logged in user. If you are using Thymeleaf, you need to add additional dependency in your pom.xml to enable suppport for Spring Security Dialect using the Thymeleaf – Spring Security integration modules.

<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity5</artifactId>
     <version>3.0.4.RELEASE</version>
</dependency>

3.1. Logout Using GET

If you can’t perform a POST request and like to fall back to GET logout request, you need the following changes in your application.

  1. Disable CSRF.
  2. Conver POST request to GET on UI.
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
    ...
}

UI changes

<div sec:authorize="isAuthenticated()">
  <a th:href="@{/logout}">Logout</a>  
</div>

4.  Testing Logout

Our configuration and changes are complete, start the application, once application is up and running do a login.

Logged In Screen:

spring security logout

If we check the cookies, we will see the following cookies:

  1. JSESSIONID.
  2. Custom Cookie (Stored during login process)
Spring Security login cookies

When we perform the logout, Spring Security will invalidate the session and delete any additional cookie (if we configure it in the logout configuration). To check this, perfrom the following additional steps

  1. Note down the JSESSIONID id after the login.
  2. Do a logout and check the JSESSIONID again, both ID will be different.

Here is the screen after logout:

Spring security logout example

dummyCookie is no longer available post logout since we told Spring security to delete it on successful logout.

protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
    ...
    .logout(logout->logout
       .deleteCookies("dummyCookie")
    );
}

Summary

In this post, we looked at the Spring security logout feature. Spring security provides build in support for the logout with a small configuration and code changes. At the same time it’s flexible enough to allow you to customize the logout behaviour for your application. In Summary:

  1. How to perfrom the logout in Spring  application.
  2. What are the configuration required to enable logout feature?
  3. How to customize the logout behaviout by injecting your own logout success handlers.

This post is part of our Spring security course and the code base is available on the GitHub