{{announcement.body}}
{{announcement.title}}

Spring Boot + OpenID Connect: Logout Options

DZone 's Guide to

Spring Boot + OpenID Connect: Logout Options

We talk a lot about login. However, there are considerations to take into account when configuring logout.

· Java Zone ·
Free Resource

We tend to talk a lot about what it takes to safely log into an application. This stems from the fact that, once you secure login, log out automatically works, too. However, there are still some considerations to take into account when configuring your logout.

This post will use Spring Security to examine two options for logout: “default” session clearing logout and party initiated logout. 

For those who are just starting out with  OAuth 2.0 or OpenID Connect (OIDC), there’s a great article I recommend—An Illustrated Guide to OAuth and OpenID Connect—which you should check out if you want to learn more.

Prerequisites:

Spring Security’s Default Logout

By default, when logging out of a Spring application, Spring removes the current session (technically it invalidates it) along with the corresponding session cookie (typically JSESSIONID). Finally, Spring redirects the user to a new page (which by default is /login?logout). Other than removing any ID and access tokens from your application’s session, nothing OAuth 2.0/OIDC specific happens.

The examples below are configured to redirect to the root page /.

What is RP-Initiated Logout

RP-Initiated Logout is a bit of a mouthful, but the RP means relying party, which in OAuth 2.0/OIDC terms is just your application. Simplified, this means your application triggers the end of the session with your identity provider (IdP). Some folks refer to this as "SSO Logout" because this would end the session for any applications configured for single sign-on (SSO).

This flow does everything the above "default" logout does, but, instead of redirecting to a page with the application, it redirects to the IdP, where the IdP performs its logout action, and then finally redirects back to your application.

The redirect URI looks like this, where the post_logout_redirect_uri is the page to return to in your application.

HTTP
 




x


1
https://dev-123456.okta.com/oauth2/default/v1/logout?id_token_hint=<id-token>&post_logout_redirect_uri=http://localhost:8080/


After hearing this explanation, you might be thinking, isn’t that what I want? Why is that not the default? My answer is usually, "it depends, but probably not."

Which Logout Option is Right for Me?

Nobody likes the answer "it depends," so I’ll give you a couple of common examples.

I think social authentication is one of the easiest ways to see the difference between the use cases. With social authentication, your application isn’t controlling the user’s session with the IdP, only the session within your application. A more concrete way to look at it is Google wouldn’t allow your application’s logout to also log you out of your Gmail. Most corporate SSOs and portals work this way too. In that case, you might want to go with the default logout option.

On the flip side, if you only have a single application, then from a user’s perspective, that is the only way they interact with the IdP so that RP-Initiated logout could be the right choice.

Enough Already—Show Me Some Code

I’ve built a simple Spring Boot app that has two pages, a landing page at / that anyone can access, and a /profile page that requires authentication to view. This application also uses Thymeleaf, but that is an implementation detail; we are only going to be looking at the security configuration.

Grab the project from GitHub:

Java
 




xxxxxxxxxx
1


 
1
git clone https://github.com/oktadeveloper/okta-spring-logout-example.git
2
cd okta-spring-logout-example


Create an Okta OIDC Application

Log in to your Okta dashboard, (if you just signed up, Okta will email login instructions to you) then:

Your app’s settings should look as follows.

App Settings

You will find your Client ID and Client secret on this page. Copy them into src/main/resources/application.properties:

Properties files
 




xxxxxxxxxx
1


1
spring.security.oauth2.client.provider.okta.issuer-uri={yourOktaDomain}/oauth2/default
2
spring.security.oauth2.client.registration.okta.client-id={client-id-from-above}
3
spring.security.oauth2.client.registration.okta.client-secret={client-secret-from-above}


Never store secrets in source control! Spring Boot supports many different options to load configuration.

For example, the same configuration with environment variables would be:

Java
 




xxxxxxxxxx
1


1
SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_OKTA_ISSUER_URI={yourOktaDomain}/oauth2/default
2
SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_OKTA_CLIENT_ID={client-id-from-above}
3
SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_OKTA_CLIENT_SECRET={client-secret-from-above}


Start the application with ./mvnw spring-boot:run and browse to http://localhost:8080/ in a private/incognito window.

Private/incognito window

Click the Login button.

Login button

Now the fun part. Click the Logout button. The app has logged you out and sent you back to /. However, if you press the Login button again, you will be automatically logged in; this is because only your application’s session was deleted, not the session with Okta.

If you inspect the network traffic in your browser, you will see you redirected back to your Okta Organization and then back again.

Configure RP-Initiated Logout with Spring Security

If you open src/main/java/com/okta/example/LogoutExampleApplication.java, you will see the following WebSecurityConfigurerAdapter class:

Java
 




xxxxxxxxxx
1
21


1
@Configuration
2
static class SecurityConfig extends WebSecurityConfigurerAdapter {
3
 
          
4
    @Override
5
    protected void configure(HttpSecurity http) throws Exception {
6
        http.authorizeRequests()
7
 
          
8
                // allow anonymous access to the root page
9
                .antMatchers("/").permitAll()
10
 
          
11
                // all other requests
12
                .anyRequest().authenticated()
13
 
          
14
                // After we logout, redirect to root page,
15
                // by default Spring will send you to /login?logout
16
                .and().logout().logoutSuccessUrl("/")
17
 
          
18
                // enable OAuth2/OIDC
19
                .and().oauth2Login();
20
    }
21
}


Change this class to:

Java
 




xxxxxxxxxx
1
29


 
1
@Configuration
2
static class SecurityConfig extends WebSecurityConfigurerAdapter {
3
 
          
4
    @Autowired
5
    ClientRegistrationRepository clientRegistrationRepository; 
6
 
          
7
    OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler() { 
8
        OidcClientInitiatedLogoutSuccessHandler successHandler = new OidcClientInitiatedLogoutSuccessHandler(clientRegistrationRepository);
9
        successHandler.setPostLogoutRedirectUri(URI.create("http://localhost:8080/"));
10
        return successHandler;
11
    }
12
 
          
13
    @Override
14
    protected void configure(HttpSecurity http) throws Exception {
15
        http.authorizeRequests()
16
 
          
17
                // allow anonymous access to the root page
18
                .antMatchers("/").permitAll()
19
 
          
20
                // all other requests
21
                .anyRequest().authenticated()
22
 
          
23
                // RP-initiated logout
24
                .and().logout().logoutSuccessHandler(oidcLogoutSuccessHandler()) 
25
 
          
26
                // enable OAuth2/OIDC
27
                .and().oauth2Login();
28
    }
29
}


  1. Inject the ClientRegistrationRepository
  2. Create a OidcClientInitiatedLogoutSuccessHandler
  3. Replace logoutSuccessUrl("/") withlogoutSuccessHandler(oidcLogoutSuccessHandler())

Restart the application and log in and out a few times. You will be prompted to log in every time you press the Login button.

Bonus: Use the Okta Spring Boot Starter

If you are using the Okta Spring Boot Starter, you can configure an RP-Initated Logout by setting the okta.oauth2.postLogoutRedirectUri property such as:

Properties files
 




xxxxxxxxxx
1


 
1
okta.oauth2.postLogoutRedirectUri=http://localhost:8080/


Learn More about Okta and Spring Security

In this post, I’ve explained the two types of logout options you have with Spring Security. Which option you pick is up to you and how you want your application to behave.

If you like this blog post and want to see more like it, follow @oktadev on Twitter, subscribe to our YouTube channel, or follow us on LinkedIn. As always, please leave a comment below if you have any questions.

Topics:
java 8, oauth, okta, open id connect, secure login, spring

Published at DZone with permission of Brian Demers , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}