I have a Spring app -- not a Spring Boot app -- that I'm trying to declare a section of the API as OAuth2 protected using Spring Security. My authorization and general resource access config works great when I define http
elements in the XML, but when I try to implement the resource access blocks using ResourceServerConfigureAdapter#configure(HttpSecurity)
-- complete with @EnableResourceServer
etc, that configure
method never even fires (end to end tests also fail). Example Java config below:
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("oauth2/control");
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/api/**")
.authorizeRequests().anyRequest().hasRole("OAUTH_USER").and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// before=PRE_AUTH_FILTER
.addFilterBefore(oAuth2AuthenticationProcessingFilter, AbstractPreAuthenticatedProcessingFilter.class)
.csrf().disable()
.anonymous().disable()
.exceptionHandling()
.accessDeniedHandler(oAuth2AccessDeniedHandler)
.authenticationEntryPoint(loginUrlAuthenticationEntryPoint);
}
I have tried declaring a few different ways of effecting the config, but no dice. Namely, I have tried both top level @Configuration
classes extending ResourceServerConfigurerAdapter
and bean methods returning ResourceServerConfiguration
as in Dave Syer's example; I've also tried explicitly setting order to Ordered.HIGHEST_PRECEDENCE
on the appropriate beans.
It's quite possibly important to note that most of the application's legacy security config is defined via XML elements like the above. Another possible red flag about my configuration -- in order to get the token endpoint to authenticate against basic auth client_id:client_secret I had to wire my own BasicAuthFilter(ProviderManager(DaoAuthProvider(ClientUserDetailsService(clientDetailsService)))))
when, because it's the vanilla and 'right' way to authenticate the token endpoint, I'd expect spring config to just default to it.
Anyway, in no situation can I get ResourceServerConfigureAdapter#configure(HttpSecurity)
to fire. My going theories are:
Something about the preceding XML HTTP blocks is preventing my
configure
method from ever even being called
This is simply a Spring Boot only feature -- although I've seen no language to that effect
There's straight up some object in the application context that I'm missing (again, the operative annotations that I have at work -- besides the obvious @Configuration
and @Bean
-- are @EnableWebSecurity
, @EnableAuthenticationServer
, and @EnableResourceServer
).
I've made some configuration error (duh).
Any examples would be much appreciated
Example OAuth2 configuration class (one of a few different iterations) below:
@Configuration
@EnableWebSecurity
@EnableResourceServer
public class OAuth2Configuration {
... etc ...
@Bean
public ResourceServerConfiguration adminResources() {
// copped from https://github.com/spring-projects/spring-security-oauth/tree/master/tests/annotation/multi
ResourceServerConfiguration resource = new ResourceServerConfiguration() {
public void setConfigurers(List<ResourceServerConfigurer> configurers) {
super.setConfigurers(configurers);
}
};
resource.setConfigurers(Collections.singletonList(new ResourceServerConfigurerAdapter() {
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("oauth2/control");
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/api/**")
.authorizeRequests().anyRequest().hasRole("OAUTH_USER").and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// before=PRE_AUTH_FILTER
.addFilterBefore(oAuth2AuthenticationProcessingFilter, AbstractPreAuthenticatedProcessingFilter.class)
.csrf().disable()
.anonymous().disable()
.exceptionHandling()
.accessDeniedHandler(oAuth2AccessDeniedHandler)
.authenticationEntryPoint(loginUrlAuthenticationEntryPoint);
}
}));
resource.setOrder(Ordered.HIGHEST_PRECEDENCE);
return resource;
}
@Configuration
@EnableAuthorizationServer
public static class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
... etc ...
}
}
Analogogous <http>
config that is picked up:
<sec:http pattern="/api/**" create-session="stateless"
entry-point-ref="loginUrlAuthenticationEntryPoint">
<sec:anonymous enabled="false" />
<sec:csrf disabled="true"/> <!-- csrf tokens don't make sense for a 3rd party API -->
<sec:custom-filter ref="oauth2ProcessingFilter" before="PRE_AUTH_FILTER"/>
<sec:access-denied-handler ref="oauthAccessDeniedHandler" />
<sec:intercept-url pattern="/api/**" access="hasRole('OAUTH_USER')" />
</sec:http>
If you are simultaneously using both Java-based and XML-based security configuration, only the XML-based will be picked up. Have you tried disabling/commenting-out all your XML-based http security config and see if your Java-based would activate?
I had a similar problem before. I asked help at the Spring Security Gitter channel and also did some investigation. See below:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With