0

I have a SpringBoot application with spring security. We have two path one for actuators : /actuator/** and one for our specific apis : /api/v1/mail/**.

I would like to apply a filter (ApiKeyFilter) only when a request is issued to /api/v1/mail/something and not when /actuator/something is called!

My configuration looks like :

@EnableWebSecurity 
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

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

        @Override
        protected void configure(HttpSecurity http) throws Exception {
           http.antMatcher("/actuator/**").authorizeRequests().anyRequest().permitAll();
        }
    }

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

        @Autowired
        private ApiKeyFilter filter;

        private static final RequestMatcher PRIVATE_URLS = new AntPathRequestMatcher("/api/v1/mails/**");

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/api/**")
                .exceptionHandling()
                .defaultAuthenticationEntryPointFor(forbiddenEntryPoint(), PRIVATE_URLS)
                .and()
                .authorizeRequests()
                .antMatchers("/api/vi/mails/**")
                .authenticated()
                .and()
                .addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class)
                .csrf().disable().httpBasic().disable().formLogin().disable().logout().disable();
        }

        @Bean
        AuthenticationEntryPoint forbiddenEntryPoint() {
            return new HttpStatusEntryPoint(HttpStatus.FORBIDDEN);
        }
    }
   }

With this code my filter (ApiKEyFilter) is invoked when calling /actuator/health and when calling /api/vi/mail/retrieve that's not what i expected!

ApiKeyFilter :

@Component
public class ApiKeyFilter extends GenericFilterBean {

    private static final Logger LOGGER =    LoggerFactory.getLogger(ApiKeyFilter.class);

    private final String API_KEY = "ApiKey";

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        final String authParam = ofNullable(((HttpServletRequest) servletRequest).getHeader(HttpHeaders.AUTHORIZATION)).orElse(servletRequest.getParameter(API_KEY));

        final String token = ofNullable(authParam).map(value -> StringUtils.removeStart(value, API_KEY)).map(String::trim)
            .orElseThrow(() -> new BadCredentialsException("Missing api key"));
        LOGGER.debug(token);

       filterChain.doFilter(servletRequest, servletResponse);
    }
}
Nemesis
  • 2,750
  • 2
  • 22
  • 20
  • try to add as many `antMatchers()` as HttpMethods, you want to allow, into your second configuration nested class after the `authorizeRequests` method, and pass into it the allowed method and the endpoint, and chain the `permitAll()` method. – Gigaxel Feb 06 '19 at 14:56
  • can't see how it'll prevent filter execusion. tried to permitAll() on /actuator/** before asking for help but it doesn't solve the current problem of erroneous filter execution – Nemesis Feb 06 '19 at 15:47
  • @Nemesis Your filter is exposed and Spring Boot adds all beans implementing `Filter` as servlet filter. You have to disable the servlet filter, see anwser of the other question. – dur Feb 06 '19 at 21:16

0 Answers0