Custom HTTP configuration configuration with OAuth2 Resource Server

I use Spring Security OAuth2with a very simple configuration that works fine. Now I want to have a separate WebSecurityConfigurerAdapterone that contains custom logic that determines if someone has permissions to access some endpoints. However, it fails no matter what I try to do. Below are my configurations OAuth2and my conclusions on this topic. Authorization Server:

@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private AuthenticationManagerBuilder authenticationManager;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints)throws Exception {
        endpoints.authenticationManager(authentication -> authenticationManager.getOrBuild().authenticate(authentication)).tokenStore(tokenStore);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory().withClient("CLIENT_NAME")...;
    }

}

Resource Server:

@Configuration
@EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Autowired
    private TokenStore tokenStore;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated();
    }

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

. WebSecurityConfigurerAdapter , . EnableResourceServer -annotated bean WebSecurityConfigurerAdapter Order(3), , /, WebSecurityConfiguration . , WebSecurityConfiguration Order(2) , access , , ( bean @EnableResourceServer ).

@EnableWebSecurity
@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Bean
    public TokenStore tokenStore() {
        return new InMemoryTokenStore();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/...");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();

        http.authorizeRequests().antMatchers(HttpMethod.GET, "/path/**")
        .access("@security.hasPermission(authentication, 'SOME', 'VALUE')");

        http.authorizeRequests().anyRequest().authenticated();
    }
}

, @security access Spring bean:

@Component("security")
public class SecurityService {
    public boolean hasPermission(Authentication authentication, String param, String anotherParam) { ... }
}

, WebSecurityConfiguration, ( ). , http .

+4
3

, oauth2, API ( Authorization Bearer [TOKEN]), , .

, spring boot 1.5+, application.properties: security.oauth2.resource.filter-order=3 (1.5 )

.

spring MethodSecurityExpressionHandler , - DefaultMethodSecurityExpressionHandler. OAuth2MethodSecurityExpressionHandler oauth2, .

MethodSecurityExpressionOperations, SecurityExpressionRoot .

-, MethodSecurityExpressionOperations. // custom logic methods ( spring, ):

public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {

    // Based on MethodSecurityExpressionRoot (class is package private in spring)
    private Object filterObject;
    private Object returnObject;
    private Object target;

    CustomMethodSecurityExpressionRoot(Authentication a) {
        super(a);
    }

    public void setFilterObject(Object filterObject) {
        this.filterObject = filterObject;
    }

    public Object getFilterObject() {
        return filterObject;
    }

    public void setReturnObject(Object returnObject) {
        this.returnObject = returnObject;
    }

    public Object getReturnObject() {
        return returnObject;
    }

    /**
     * Sets the "this" property for use in expressions. Typically this will be
     * the "this" property of the {@code JoinPoint} representing the method
     * invocation which is being protected.
     *
     * @param target
     *            the target object on which the method in is being invoked.
     */
    void setThis(Object target) {
        this.target = target;
    }

    public Object getThis() {
        return target;
    }

    // custom logic methods
    public boolean securityHasPermission(String param, String anotherParam) {
        /* custom logic here */
    }

, MethodSecurityExpressionHandler:

public class CustomOAuth2MethodSecurityExpressionHandler extends OAuth2MethodSecurityExpressionHandler {

    private final AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();

    @Override
    protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication,
            MethodInvocation invocation) {
        final CustomMethodSecurityExpressionRoot root = new CustomMethodSecurityExpressionRoot(authentication);
        root.setThis(invocation.getThis());
        root.setPermissionEvaluator(getPermissionEvaluator());
        root.setTrustResolver(this.trustResolver);
        root.setRoleHierarchy(getRoleHierarchy());

        return root;
    }

}

MethodSecurityExpressionHandler. , GlobalMethodSecurityConfiguration. @Bean MethodSecurityExpressionHandler createExpressionHandler(), :

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class Oauth2GlobalMethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        return methodSecurityExpressionHandler();
    }

    @Bean
    public MethodSecurityExpressionHandler methodSecurityExpressionHandler() {
        return new CustomOAuth2MethodSecurityExpressionHandler();
    }

@PreAuthorize("securityHasPermission('SOME', 'VALUE')"),

CustomMethodSecurityExpressionRoot, authentication, . /beans CustomOAuth2MethodSecurityExpressionHandler.

0

: -, .

:

OAuth2AuthorizationServerConfig

clients.inMemory().withClient("CLIENT_NAME").authorities("ADMIN")....;

,

 http.authorizeRequests().antMatchers(HttpMethod.GET, "/path/**")
    .hasAuthority("ADMIN");

/

 @PreAuthorize("hasAuthority('ADMIN')")
+3

OAuth2MethodSecurityExpressionHandler bean.

:

@EnableGlobalMethodSecurity(prePostEnabled = true)
public class OAuth2ResourceServerConfig extends GlobalMethodSecurityConfiguration {

        @Override
        protected MethodSecurityExpressionHandler createExpressionHandler() {
             return new OAuth2MethodSecurityExpressionHandler();
        }

        ....
}

:

@EnableGlobalMethodSecurity(prePostEnabled = true)
public class OAuth2ResourceServerConfig extends GlobalMethodSecurityConfiguration {

        @Override
        protected MethodSecurityExpressionHandler createExpressionHandler() {
             return getOAuth2MethodSecurityExpressionHandler();
        }

        @Bean
        public OAuth2MethodSecurityExpressionHandler getOAuth2MethodSecurityExpressionHandler() {
             return new OAuth2MethodSecurityExpressionHandler();
        }

        ....
}

, !

0

All Articles