Upgrading to Spring-Security 5.7.0 SecurityContextPersistenceFilter not called

261 Views Asked by At

With WebSecurityConfigurerAdapter being deprecated in Spring-security 5.7.0 we are trying to migrate to the newer way to configuring securityFilterChain but in doing so i noticed in spring debug log that the SecurityContextPersistenceFilter isnt invoked. As a result when testing controllers with a requestPostProcessor the authentication set within the requestPostProcessor doesnt get applied to the HttpSession when the request is being authenticated.

Logs post the version upgrade

[main] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - Created HttpSession as SecurityContext is non-default
[main] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - Stored SecurityContextImpl [Authentication=TestAuthenticationToken [Principal=ApiUser [Username=USER, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[placeholder]], Credentials=[PROTECTED], Authenticated=true, Details=null, Granted Authorities=[]]] to HttpSession [org.springframework.mock.web.MockHttpSession@153d14e3]
[main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - POST "/v1/api_path”, parameters={}
[main] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.xyz.Controller#controllerMethod(String, List)

Logs before the version upgrade

HttpSession as SecurityContext is non-default
[main] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - Stored SecurityContextImpl [Authentication=TestAuthenticationToken [Principal=ApiUser [Username=USERNAME, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[placeholder]], Credentials=[PROTECTED], Authenticated=true, Details=null, Granted Authorities=[]]] to HttpSession [org.springframework.mock.web.MockHttpSession@d641499]
[main] DEBUG org.springframework.security.web.FilterChainProxy - Securing POST /v1/api_path
[main] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - Retrieved SecurityContextImpl [Authentication=TestAuthenticationToken [Principal=ApiUser [Username=USERNAME, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[placeholder]], Credentials=[PROTECTED], Authenticated=true, Details=null, Granted Authorities=[]]]
[main] DEBUG org.springframework.security.web.context.SecurityContextPersistenceFilter - Set SecurityContextHolder to SecurityContextImpl [Authentication=TestAuthenticationToken [Principal=ApiUser [Username=USERNAME, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[placeholder]], Credentials=[PROTECTED], Authenticated=true, Details=null, Granted Authorities=[]]]
[main] DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Authorized filter invocation [POST /v1/api_path] with attributes [authenticated]
[main] DEBUG org.springframework.security.web.FilterChainProxy - Secured POST /v1/api_path
[main] DEBUG org.springframework.test.web.servlet.TestDispatcherServlet - POST "/v1/api”_path, parameters={}
[main] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.Controller#ControllerMethod(String, List)

Here's the code changes made to the SecurityConfig NEW CODE

    /**
     * Configure in memory authentication with the default username/password.
     * @return InMemoryUserDetailsManager {@link InMemoryUserDetailsManager}
     */
    @Bean
    public InMemoryUserDetailsManager configureAuthentication() {
        final UserDetails userDetails = new User(DEFAULT_USERNAME, DEFAULT_PASSWORD, authorities(DEFAULT_ROLES));
        return new InMemoryUserDetailsManager(userDetails);
    }

    /**
     * Security Filter chain for Http requests.
     * @param http HttpSecurity
     * @return SecurityFilterChain for Http requests
     */
    @Bean
    public SecurityFilterChain filterChain(final HttpSecurity http) throws Exception {
        http.authorizeRequests(auth ->
                auth.anyRequest().authenticated())
                .httpBasic()
                .and()
                .csrf().disable();
        return http.build();
    }

    /**
     * Set the default ignore everything on the security context.
     * @return WebSecurityCustomizer - used to customize WebSecurity
     */
    @Bean
    public WebSecurityCustomizer ignoringCustomizer() {
        return web -> web.ignoring().antMatchers("/**");
    }

OLD CODE

 @Autowired
    public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser(DEFAULT_USERNAME)
                .password(DEFAULT_PASSWORD)
                .roles(DEFAULT_ROLES.toArray(new String[0]));
    }

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .httpBasic()
                .and()
                .csrf().disable();
    }

    /**
     * Set the default ignore everything on the security context.
     *
     * @param web {@link WebSecurity}.
     */
    protected static void setIgnoreEverything(final WebSecurity web) {
        web.ignoring().antMatchers("/**");
    }
1

There are 1 best solutions below

0
woggle On

Realized in debugging that in the legacy code there were duplicate security filter chains but the order of their execution had been flipped and so the securityfilterchain with antpatter /** was being executed first and hence bypassing the securityContextpersistencefilter. Solution was to remove the /** antpattern since it wasnt serving any purpose.