4

I'm trying to implement a simple spring boot project. I got several REST-Endpoints which I've to secure differently. One has to be secured by Basic Auth, another one with OAuth and one with a custom security implementation.

REST-Endpoints:

  • /basic/auth
  • /application/secure (oauth)
  • /application/secure2 (own implementation)

From tutorials, I know I've to set the order of the security adapters. My first intention was to set the order in steps of ten (e.g. @Order(10), @Order(20)) in case I need to add other security filters in between. By doing so I investigated the following behavior:

  • If I add the basic auth filter with @Order(10) and an OAuth filter with @Order(20) only the OAuth filter works.
  • If I add the basic auth filter with @Order(1) or @Order(2) and an OAuth filter with @Order(4) both filters works.
  • If I add a filter to @Order(3) I receive an error which says, that order 3 is already in use and cannot be configured twice.

So there is a default spring security adapter (or whatever) which has the default order 3. I thought I disable every default spring security behavior by adding @EnableWebSecurity. After I did not find an answer by google my questions would be:

  • Am I doing the right things?
  • What is this security adapter with order 3 by spring?
  • Does the default security adapter block my basic auth implementation?

WebSecurityConfig:

   @Configuration
   @EnableWebSecurity
   public class WebSecurityConfig {

    @Order(10)
    @Configuration
    public class BasicAuthConfig extends WebSecurityConfigurerAdapter {
        @Value("${security.user.password}")
        private String password;
        @Value("${security.user.name}")
        private String username;

        private static final String ROLE_ADMIN = "ADMIN";

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication().withUser(username).password(password).roles(ROLE_ADMIN);
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable();
            http.requestMatchers().antMatchers("/basic/**", "/") //
                    .and().authorizeRequests().anyRequest().authenticated() //
                    .and().httpBasic();
        }
    }

    @Order(20)
    @Configuration
    @EnableResourceServer
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    protected static class Oauth2ServerConfig extends ResourceServerConfigurerAdapter {
        @Override
        public void configure(HttpSecurity http) throws Exception {
            System.out.println("Filter called");
            // @formatter:off
            http.csrf().disable();
            http.authorizeRequests().antMatchers("/application/**").authenticated()
                    // .antMatchers(GET, "/application/secure").authenticated()
                    .anyRequest().authenticated(); 
            // @formatter:on
        }

     // offline token validator

    }
monti
  • 455
  • 7
  • 25
  • 1
    See https://stackoverflow.com/a/49429040/5277820 – dur Mar 23 '18 at 09:38
  • mh, I still don't get why a new `WebSecurityConfigurerAdapter` wouldn't be called if the `order` is set to a bigger value then 3. Shouldn't this be called afterward or match when the request path is called? Does the `WebSecurityConfigurerAdapter` which is created by the `@EnableResourceServer` overwrites every other `WebSecurityConfigurerAdapter`? This would mean I'm limited to two filter while using a `@EnableResourceServer`. – monti Mar 23 '18 at 11:46
  • 1
    It is important to understand, that only one configuration is applied. The first one in the chain **matching the request**. All others are not applied. – dur Mar 23 '18 at 12:38
  • But a call to `/basic/auth` does not match a call to `/application/secure`. So even if the basic auth filter got an `order` bigger than 3 it should be matching, shouldn't it? – monti Mar 23 '18 at 14:59
  • Why do both configurations match `/**` ? For one it's `/basic/**` and `/` and for the other one its `/application/**`. A call to everything else should be denied, shouldn't it? – monti Mar 26 '18 at 07:33
  • 1
    No, for `BasicAuthConfig` it is `/basic/**` and `/` and for `Oauth2ServerConfig` it is `/**`. – dur Mar 26 '18 at 09:22
  • Could you please explain why `/**` is a matcher for `Oauth2ServerConfig `? – monti Mar 26 '18 at 11:47
  • 1
    See https://stackoverflow.com/questions/33603156/spring-security-multiple-http-config-not-working/33608459#33608459 and https://stackoverflow.com/a/41527591/5277820. – dur Mar 26 '18 at 12:05
  • I tested and read a little bit more. `Oauth2ServerConfig` matches `/**` because there is no requestMatcher. So if I want to have filters after the `order` of `3`. I need to add a request filter to `/application/**`. – monti Mar 29 '18 at 11:07

1 Answers1

2

This is an old question, but if anyone is still wondering what the issue is, here are my observations:

  • @EnableResourceServer imports ResourceServerConfiguration, which has an order of 3.
  • There are ways that may allow you to add more than 2 filters before the order 3 resource server configurer, for instance
    • by giving some of them negative order values (Although I don't suppose negative values would be any special, one would need to take into account other implicit web security configurers -- for instance the one with order 0 -- enabled by default. This however means there is a possibility of collision between filters in different versions of the framework as new features are introduced);
    • by adding them as resource configurers (The ResourceServerConfiguration class does not add any request matchers, but enforces a fallback to anyRequest().authenticated() if the user has not configured anything).
  • For a better understanding on how paths are matched in the configured request matchers, you can take a quick glance at Ant path patterns.
Butshuti
  • 61
  • 4