Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom Authentication Filters in multiple HttpSecurity objects using Java Config

I want to have two different http web configurations with custom authentication filters using spring boot and spring java config. I followed the sample application that can be found here: https://github.com/spring-projects/spring-security-javaconfig/blob/master/samples-web.md#sample-multi-http-web-configuration. My understanding was, that this would end up in a separate spring filter chain for each of the web configurations. But both filters are invoked although the web configuration url pattern doesn't match the request. For instance, requesting http://localhost:8080/api/dosomething will invoke both filters, not only CustomApiAuthenticationFilter. Of course, it would be possible to check the request url in doFilterInternal and ignore the request if it doesn't match but I thought this should be done automatically by respecting the url pattern of the corresponding web configuration. Furthermore, my RestController doesn't get called respectively Postman only receives Status Code 200 OK with no response body.

Two questions: 1. Is this behaviour by design or is the configuration wrong? 2. Why is my RestController not invoked?

@EnableWebSecurity
public class SecurityConfiguration {

    @Configuration
    @Order(1)
    public static class ApiConfigurationAdapter extends WebSecurityConfigurerAdapter {

        @Bean
        public GenericFilterBean apiAuthenticationFilter() {
            return new CustomApiAuthenticationFilter();
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {

            http.antMatcher("/api/**").addFilterAfter(apiAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class)
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests().antMatchers("/api/**").authenticated();
        }
    }

    @Configuration
    @Order(2)
    public static class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

        @Bean
        public GenericFilterBean webAuthenticationFilter() {
            return new CustomWebAuthenticationFilter();
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/").addFilterAfter(webAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class)
                .authorizeRequests().antMatchers("/").authenticated();
        }
    }
}

public class CustomApiAuthenticationFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        Authentication auth = new UsernamePasswordAuthenticationToken("sub", "password", ImmutableList.of(new SimpleGrantedAuthority("API")));
        SecurityContextHolder.getContext().setAuthentication(auth);
    }
}

public class CustomWebAuthenticationFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        Authentication auth = new UsernamePasswordAuthenticationToken("sub", "password", ImmutableList.of(new SimpleGrantedAuthority("USER")));
        SecurityContextHolder.getContext().setAuthentication(auth);
    }
}

@RestController
public class ApiController {
    @RequestMapping(value = "/api/v1/dosomething", method = RequestMethod.GET)
    public String getSomething() {
        return "something";
    }
}
like image 709
oliver Avatar asked Nov 09 '22 15:11

oliver


1 Answers

Thanks to M. Deinum who gave me the right answer. The following now works as expected but still I'm not sure if this is a legitimate approach.

@EnableWebSecurity
public class SecurityConfiguration {

    @Configuration
    @Order(1)
    public static class ApiConfigurationAdapter extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {

            http.antMatcher("/api/**")
                .addFilterAfter(new CustomApiAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class)
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests().anyRequest().hasRole("API");
        }
    }

    @Configuration
    @Order(2)
    public static class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/")
                .addFilterAfter(new CustomWebAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class)
                .authorizeRequests().anyRequest().hasRole("USER");
        }
    }
}

public class CustomApiAuthenticationFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        Authentication auth = new UsernamePasswordAuthenticationToken("sub", "password", ImmutableList.of(new SimpleGrantedAuthority("ROLE_API")));
        SecurityContextHolder.getContext().setAuthentication(auth);
        filterChain.doFilter(request, response);
    }
}

public class CustomWebAuthenticationFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        Authentication auth = new UsernamePasswordAuthenticationToken("sub", "password", ImmutableList.of(new SimpleGrantedAuthority("ROLE_USER")));
        SecurityContextHolder.getContext().setAuthentication(auth);
        filterChain.doFilter(request, response);
    }
}
like image 130
oliver Avatar answered Nov 14 '22 22:11

oliver