Summary

When configuring a global ServerSecurityContextRepository on the SecurityWebFilterChain, it is used by all authentication mechanisms (since #7249) but not by the logout handler.

Actual Behavior

When configuring a custom ServerSecurityContextRepository, the SecurityContextServerLogoutHandler still uses the default WebSessionServerSecurityContextRepository.

Expected Behavior

I’d expect that the ServerHttpSecurity.securityContextRepository () method sets the ServerSecurityContextRepository everywhere.

Configuration

@Configuration
@EnableWebFluxSecurity
@EnableWebFlux
public class Main extends AbstractReactiveWebInitializer {

  @Bean
  public SecurityWebFilterChain springSecurityFilterChain (ServerHttpSecurity http) {
    return http
        .securityContextRepository (securityContextRepository ())
        .formLogin ()
            .and ()
        .logout ()
            .logoutUrl ("/logout")
            .and ()
        .build ();
  }

  @Bean
  public ServerSecurityContextRepository securityContextRepository () {
    return new CustomSecurityContextRepository ();
  }

  @Bean
  public ReactiveUserDetailsService userDetailsService () {
    var user = User.withDefaultPasswordEncoder ()
        .username ("user")
        .password ("user")
        .roles ("USER")
        .build ();
    return new MapReactiveUserDetailsService (user);
  }

  @Override
  protected Class<?>[] getConfigClasses () {
    return new Class<?>[] { Main.class };
  }

}

Version

  • Spring Security : 5.3.0.RELEASE
  • Spring Framework : 5.2.5.RELEASE

Sample

https://github.com/EtienneMiret/spring-security-logout

Comment From: rwinch

Thanks for the report. I have confirmed this is an issue. I will push a fix out. In the meantime, you can work around it by explicitly providing a logout handler. So changing your example to be something like this would work:

@Bean
public SecurityWebFilterChain springSecurityFilterChain (ServerHttpSecurity http, ServerSecurityContextRepository repository) {
  SecurityContextServerLogoutHandler handler = new SecurityContextServerLogoutHandler();
  handler.setSecurityContextRepository(repository);
  return http
      .securityContextRepository (repository)
      .formLogin ()
          .and ()
      .logout ()
          .logoutHandler(handler)
          .logoutUrl ("/logout")
          .and ()
      .build ();
}

@Bean
public ServerSecurityContextRepository securityContextRepository () {
  return new CustomSecurityContextRepository ();
}

Comment From: rwinch

Thanks again for the ticket. This is fixed in master and backported to 5.3.x 5.2.x and 5.1.x.

Comment From: EtienneMiret

You’re welcome. I’m glad it was indeed an issue, and not a misunderstanding on my side. I would’ve hated to waste your time.

Comment From: rwinch

No problem. Did the workaround work for you in the meantime?

Comment From: EtienneMiret

Yes! The workaround works fine. Thank you!