0
votes

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

1 Answers

0
votes

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.