Describe the bug

A custom SecurityContextRepository that is configured for a SecurityFilterChain will be ignored by SessionManagementConfigurer/SessionManagementFilter. Instead the SessionManagementFilter uses the default HttpSessionSecurityContextRepository.

This happens in Spring Security 6.0.x. The issue did not appear in Spring Security 5.7.x.

The SessionManagementFilter is created when the method SessionManagementConfigurer#configure(H http) is called (see here).

In Spring Security 5.7.x the SecurityContextRepository is determined by calling http.getSharedObject(SecurityContextRepository.class).

SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class);
SessionManagementFilter sessionManagementFilter = new SessionManagementFilter(securityContextRepository, getSessionAuthenticationStrategy(http));
// ....

In Spring Security 6.0.x this behavior changed. this.sessionManagementSecurityContextRepository is passed for the SessionManagementFilter constructor. See SessionManagementConfigurer

SecurityContextRepository securityContextRepository = this.sessionManagementSecurityContextRepository;
SessionManagementFilter sessionManagementFilter = new SessionManagementFilter(securityContextRepository, getSessionAuthenticationStrategy(http));

The default value for this.sessionManagementSecurityContextRepository is new HttpSessionSecurityContextRepository(). This value is only overwritten in SessionManagementConfigurer#init(H http) (see here). But NOT, if SecurityContextRepository from http.getSharedObject(SecurityContextRepository.class) is null

SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class);
    boolean stateless = isStateless();
    if (securityContextRepository == null) {
        // this.sessionManagementSecurityContextRepository is set
    }
    // No else case, where
    // this.sessionManagementSecurityContextRepository = securityContextRepository;

To Reproduce

Set a custom SecurityContextRepository in a SecurityFilterChain:

  @Bean
  public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
        .and()
        .securityContext().securityContextRepository(new MySecurityContextRepositoryImpl()); // <- set custom SecurityContextRepository
    return http.build();
  }

Unfortunately, this setting does not have any affect on SessionManagementFilter.

Expected behavior The custom SecurityContextRepository is passed to SessionManagementFilter's constructor.

Comment From: m-ibot

I created a pull request (#12583) for this issue.

If the else case in SessionManagementConfigurer is missing, the test will fail, because the SessionManagementFilter will call the containsContext method of another SecurityContextRepository but not the configured one. With the implemented else case, this issue should be solved