Search code examples
springspring-bootspring-securityspring-3security-filter

How to define two authentication mechanism for different routes in Spring Security 6?


All routing files config, except for /actuator/**, the entry point is of type "JwtAuthenticationEntryPoint" (Custom defined)

    @Bean
    @Order(1)
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(AbstractHttpConfigurer::disable)
            .cors(cors -> {})
            .authorizeHttpRequests(auth ->
                    auth.requestMatchers("**").permitAll().anyRequest().authenticated()
            )
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .exceptionHandling(handler -> handler.defaultAuthenticationEntryPointFor(entryPoint, new AntPathRequestMatcher("**")))
            .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
            .headers(headers -> headers.cacheControl(cacheControl -> {}));

        return http.build();
    }

Security config for actuator routes, the entry point is of Type "AuthenticationEntryPoint"

  @Bean
  @Order(2)
  public SecurityFilterChain actuatorSecurityFilterChain(HttpSecurity http) throws Exception {
    http
        .csrf(AbstractHttpConfigurer::disable)
        .cors(cors -> {})
        .authorizeHttpRequests(auth ->
                auth.requestMatchers("/actuator/**").permitAll()
        )
        .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
        .exceptionHandling(handler -> handler.defaultAuthenticationEntryPointFor(entryPoint, new AntPathRequestMatcher("/actuator/**")))
        .anonymous(AbstractHttpConfigurer::disable);

    return http.build();
  }

basically if one bean loads first then it overrides the other one. If I change the swap the order of the beans then actuator would work fine and other routes won't. I assume it is the problem of misconfiguring of entry point of authentication for both routes.


Solution

  • A possible approach for resolving this is to use the securityMatcher

    Using your example code:

     @Bean
      @Order(2)
      public SecurityFilterChain actuatorSecurityFilterChain(HttpSecurity http) throws Exception {
        http
            .securityMatcher("/actuator")
            .csrf(AbstractHttpConfigurer::disable)
            .cors(cors -> {})
            .authorizeHttpRequests(auth ->
                    auth.requestMatchers("/actuator/**").permitAll()
            )
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .exceptionHandling(handler -> handler.defaultAuthenticationEntryPointFor(entryPoint, new AntPathRequestMatcher("/actuator/**")))
            .anonymous(AbstractHttpConfigurer::disable);
    
        return http.build();
      }
    

    This will ensure that the provided security chain will only be applied to routes matching the pattern provided.