Skip to content
This repository was archived by the owner on May 31, 2022. It is now read-only.
This repository was archived by the owner on May 31, 2022. It is now read-only.

How to define order of spring security filter chain #1024

Closed
@kopax

Description

@kopax

How to define order of spring security filter chain

I am using the following dependency :

  • spring-boot 1.5.2.RELEASE
    • spring-boot-starter-security
  • spring-security-oauth2 2.1.0.RELEASE

I have configured two springSecurityFilterChain using:

  • (1) WebSecurityConfigurerAdapter as first security layer (Basic auth)
  • (2) ResourceServerConfigurerAdapter as second security layer. (Bearer auth)

My endpoint should be secured like this :

  1. /login (anonymous)
  2. /ping (anonymous)
  3. /oauth/** : filter (1)
  4. /**: filters (1, 2)

(1) look like this:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Order(2)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http
			.sessionManagement()
				.sessionCreationPolicy(SessionCreationPolicy.NEVER)
				.and()
			.csrf().disable()
			.authorizeRequests()
				.antMatchers(HttpMethod.GET, HttpPathStore.PING).permitAll()
				.antMatchers("/login").permitAll()
				.antMatchers("/logout").hasRole("USER")
				.antMatchers("/**").hasRole("USER")
				.anyRequest().authenticated()
			.and()
				.exceptionHandling()
				.accessDeniedHandler(accessDeniedHandler)
				.authenticationEntryPoint(authenticationEntryPoint)
			.and()
				.formLogin()
				.loginProcessingUrl(HttpPathStore.LOGIN)
				.successHandler(authenticationSuccessHandler)
				.failureHandler(authenticationFailureHandler)
				.permitAll()
			.and()
				.logout()
				.logoutUrl(HttpPathStore.LOGOUT)
				.logoutSuccessUrl(HttpPathStore.LOGIN_FROM_LOGOUT)
				.logoutSuccessHandler(logoutSuccessHandler)
				.permitAll();
	}
	...
}

(2) look like this:

@Configuration
@EnableResourceServer
@Order(3)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

	@Override
	public void configure(HttpSecurity http) throws Exception {
		http
			.authorizeRequests()
				.antMatchers(HttpMethod.GET, HttpPathStore.PING).permitAll()
				.antMatchers("/login").permitAll()
				.antMatchers("/logout").permitAll()
				.antMatchers(
					"/**"
				).access("#oauth2.hasScope('write') " +
							"and #oauth2.clientHasRole('ROLE_CLIENT') " +
							"and hasRole('USER')");
	}

	...
}

Problem

If I set @Order on:

  • (1) : @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
  • (2) : [DEFAULT]

Expected: as a user with a session and without a jwt, I expect to see the the response 401 from (2)

Result: as a user with a session and without a jwt, I have the response 401 from (1).

If I set @Order on:

  • (1) : @Order(2)
  • (2) : @Order(3)

Expected: Order the web securityFilterChain before OAuth securityFilterhChain

Result: OAuth securityFilterChain configuration seems to be ignored by spring.

Is there a way to get my configuration to have OAuth security after Basic security ?

Activity

kopax

kopax commented on Mar 17, 2017

@kopax
Author

Is related with https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-1.5-Release-Notes#oauth-2-resource-filter ?

Yes it is on the same topic. I can't tell you if my issue is due to these changes ?

Do you wan't me to redo the test on spring-boot 1.4.1.RELEASE ?

kopax

kopax commented on Mar 19, 2017

@kopax
Author

@kazuki43zoo according to your link and the setup I want. What @order value should I use for WebSecurityConfigurerAdapter and ResourceServerConfigurerAdapter ?

kazuki43zoo

kazuki43zoo commented on Mar 19, 2017

@kazuki43zoo
Contributor

Could you try as follow ?

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

	@Override
	public void configure(HttpSecurity http) throws Exception {
		http.antMatcher("/oauth/**") // ### Specify path pattern that need OAuth authentication(Bearer auth) and authorization
			.authorizeRequests()
				.antMatchers(
					"/**"
				).access("#oauth2.hasScope('write') " +
							"and #oauth2.clientHasRole('ROLE_CLIENT') " +
							"and hasRole('USER')");
	}
	...
}
kopax

kopax commented on Mar 19, 2017

@kopax
Author

@kazuki43zoo I would like to know if there is a difference between this

http.antMatcher("/oauth/**") // ### Specify path pattern that need OAuth authentication(Bearer auth) and authorization
		.authorizeRequests()
			.antMatchers(
				"/**"
			).access("#oauth2.hasScope('write') " +
						"and #oauth2.clientHasRole('ROLE_CLIENT') " +
						"and hasRole('USER')");

and this

http
		.authorizeRequests()
			.antMatchers(
                                "/oauth/**", // ### Specify path pattern that need OAuth authentication(Bearer auth) and authorization
				"/**"
			).access("#oauth2.hasScope('write') " +
						"and #oauth2.clientHasRole('ROLE_CLIENT') " +
						"and hasRole('USER')");

Could you try as follow ?

With what @Order exactly?

I did try with @Order(2), no @Order annotation on ResourceServerConfig.

Same thing as before, having @Order(2) on WebMvcSecurity result in an ignored OAuth2 security filter chain.

kazuki43zoo

kazuki43zoo commented on Mar 20, 2017

@kazuki43zoo
Contributor

In my understand ...

Default orders are as follow on Spring Boot:

  • A security filter chain that configure by a extends class of WebSecurityConfigurerAdapter -> 100
  • A resource server filter chain that configure by Spring Boot -> 2147483639 (= SecurityProperties.ACCESS_OVERRIDE_ORDER - 1)

In other words, a security filter chain that configure by a extends class of WebSecurityConfigurerAdapter will apply by default. (resource server filter chain will be not used)


If you want to apply a resource server filter chain for /oauth/***, you need to specify order as follow:

  • (1) : ACCESS_OVERRIDE_ORDER (= 2147483640)
  • (2) : [DEFAULT] (= 2147483639)

or

  • (1) : [DEFAULT] (= 100)
  • (2) : 99 or under (e.g: security.oauth2.resource.filter-order=99)

And specify a matcher pattern on (2) as follow:

http.antMatcher("/oauth/**")
    .authorizeRequests()
        ....

As result...

You can use a resource server filter chain for request that matches /oauth/** and you can use a security filter chain that configure by a extends class of WebSecurityConfigurerAdapter for other request (e.g: /login, /ping and more ... ).

If you need more information, i think you should be provide a reproduce project that can be run on GitHub.
And i think your question should be posted to the StackOverflow.

Thanks.

kopax

kopax commented on Mar 20, 2017

@kopax
Author

Thanks for the quick reply.

It seems from the javadoc that http.antMatcher("/oauth/**") is the same as http.requestMatchers().antMatchers("/oauth/**)

Allows configuring the {@link HttpSecurity} to only be invoked when matching the
provided ant pattern. If more advanced configuration is necessary, consider using
{@link #requestMatchers()} or {@link #requestMatcher(RequestMatcher)}.

I have tried both of the configuration. They seems to be able to protect the endpoint /oauth/**, but all the endpoints /** should be OAuth secure.

I have created a demo repository.

There's a README with a sum up of the security strategy.

Reproduction

  1. Clone the project

     git clone https://github.com/kopax/spring-security-oauth-issues-1024 && cd spring-security-oauth-issues-1024
    
  2. start the server

     ./gradlew build --info && java -jar build/libs/api-oauth2.jar --spring.profiles.active=default
    
  3. get a cookie

     export COOKIE=$(curl -v --silent http://localhost:8081/ 2>&1 | grep cookie -i | awk -F ' ' '{print $3}')
    
  4. authenticate the cookie

     export COOKIE=$(curl --cookie "$COOKIE" -d username=admin -d password=verysecret -v --silent http://localhost:8081/login 2>&1 | grep cookie -i | awk -F ' ' '{print $3}')
    
  5. try to get a secured oauth resource at /

     curl --cookie "$COOKIE" -v http://localhost:8081/
    

Expected

http status code 401 due to missing header Authorization

Result

http status code 200

Useful information:

Spring server:

Security account (cookie):

  • username: admin
  • password: verysecret

OAuth account (jwt):

  • client_id: myfirstapp
  • client_secret: test
  • redirect_uri: http://localhost:8081/
  • access_token_uri: http://localhost:8081/oauth/token
  • authorization_uri: http://localhost:8081/oauth/authorize
  • authorization_grant: code
  • redirect_uri: http://localhost:8081/cb/myfirstapp
kopax

kopax commented on Mar 20, 2017

@kopax
Author

Hi, It is still possible to access without a Bearer. See my reply on PR

Every configuration I have tried just can't work together on the same endpoint.
As soon a route is added to (1), it get canceled in (2).

Are you absolutely sure that spring-security and spring-security-oauth can work on the same endpoint ?

It's also possible that the API must have separate endpoints.
(I haven't found any project that use both plugin on top of each for a defined endpoint.)

stevemenke

stevemenke commented on May 4, 2017

@stevemenke

I am having the same problem. I want ldap authentication for some resources and oauth on others and can only get one or the other to work. Not both. Have you made any progress or do you have a work around?

kopax

kopax commented on May 4, 2017

@kopax
Author

It is one or the other. You can't have both.

Brandon0204

Brandon0204 commented on Oct 26, 2017

@Brandon0204

I have the same problem

masamitsunamioka

masamitsunamioka commented on Mar 17, 2018

@masamitsunamioka

Could you try following code. It works fine for me.

https://spring.io/guides/topicals/spring-security-architecture/
"The most important feature of this dispatch process is that only one chain ever handles a request."

@EnableResourceServer
@Configuration
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        super.configure(resources);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.requestMatchers()
                // For org.springframework.security.web.SecurityFilterChain.matches(HttpServletRequest)
                .requestMatchers(
                        new NegatedRequestMatcher(
                                new OrRequestMatcher(
                                        new AntPathRequestMatcher("/login"),
                                        new AntPathRequestMatcher("/logout"),
                                        new AntPathRequestMatcher("/oauth/authorize"),
                                        new AntPathRequestMatcher("/oauth/confirm_access")
                                )
                        )
                )
                .and()
                .authorizeRequests().anyRequest().authenticated();
    }
}
@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatchers()
                // For org.springframework.security.web.SecurityFilterChain.matches(HttpServletRequest)
                .requestMatchers(
                        new OrRequestMatcher(
                                new AntPathRequestMatcher("/login"),
                                new AntPathRequestMatcher("/logout"),
                                new AntPathRequestMatcher("/oauth/authorize"),
                                new AntPathRequestMatcher("/oauth/confirm_access")
                        )
                )
                .and()
                .authorizeRequests().anyRequest().authenticated()
                .and()
                .formLogin().permitAll()
                .and()
                .logout().permitAll();
    }
}
  • jdk-10+46_linux-x64
  • Spring Boot 2.0.0.RELEASE
lilalinux

lilalinux commented on Apr 14, 2018

@lilalinux

@Namioka Shouldn't ResourceServerConfiguration only match negatively on /login and /logout? And WebSecurityConfiguration negatively on /oauth/**?

masamitsunamioka

masamitsunamioka commented on Apr 29, 2018

@masamitsunamioka

@lilalinux '/oauth/authorize' and '/oauth/confirm_access' require the user authentication (Not resource server authentication by access tokens).

7 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @lilalinux@kevinojt@kopax@masamitsunamioka@stevemenke

        Issue actions

          How to define order of spring security filter chain · Issue #1024 · spring-attic/spring-security-oauth