It looks like the filter ordering changed from Spring Boot 1.4.3 to 1.5.2 (or accordingly the curated version of spring-security-oauth that comes with)...
This caused a working Bearer token setup to break out of the box after update.
Changing security.oauth2.resource.filter-order to 1 instead of 0 may have mitigated the issue.
Curious what the best/correct approach here is.
Similar issue here. After upgrading to Spring Boot 1.5.2 along with Spring OAuth 2.1, my user info endpoint began presenting the login screen even when presented with a bearer token. When no token is presented the login page is presented rather than returning a 403 response, as it does under Spring boot 1.4.4 and Spring OAuth 2.0.12. My security config is rather simple:
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// User Info endpoint
.antMatchers("/userinfo").authenticated();
}
Rolling back to 1.4.4 or applying @jzampieron suggestion fixes the problem. Unfortunately, this took a few hours to figure out.
The change in filter ordering was documented in Spring Boot 1.5 release notes. For more background you can check out spring-projects/spring-boot#5072 and spring-projects/spring-boot@fe344df9.
Okay, that helps understand the problem. However, when setting security.oauth2.resource.filter-order = 3 that fixes the the authorization issue with the /userinfo endpoint but now causes the the /login URI to respond with a 405 There was an unexpected error (type=Method Not Allowed, status=405). Request method 'POST' not supported response.
@damnhandy Can you show your complete security configuration?
Right! That might help :) For the resource server config I have:
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
private ResourceServerProperties resourceServerProperties;
@Autowired
public OAuth2ResourceServerConfig(ResourceServerProperties resourceServerProperties) {
this.resourceServerProperties = resourceServerProperties;
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId(resourceServerProperties.getId());
resources.stateless(false);
super.configure(resources);
}
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http.authorizeRequests()
// User Info endpoint
.antMatchers("/userinfo").authenticated()
// @formatter:on
}
}
And for the WebSecurityConfig I have this:
@Configuration
@Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER + 1)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
DataSource oauthDataSource;
@Autowired
public WebSecurityConfig(DataSource oauthDataSource) {
this.oauthDataSource = oauthDataSource;
}
.
/**
*
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/login").permitAll()
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.csrf().disable();
}
...
Can you try with something like this example?
Key parts are to adjust the ordering (@Order(-20)) and use requestMatchers to match only paths you intend to protect with your WebSecurityConfig.
After you do that, I believe you should also be able to use the default resource filter order (i.e. remove security.oauth2.resource.filter-order=3 from your config).
@vpavic and it works now. Seems that my WebSecurityConfig and ordering was the issue in general. The filter order is not the issue for me, but rather my own configuration. Everything now works as expected. This works for me now, and it's clear that this is not a bug but pilot error. I'm not sure if @jzampieron might have a similar issue with his config as well.
Thanks a million @vpavic , hit me up for a beer or three if you're ever in the Boston area!
@vpavic @jzampieron Hi,I meet a problem,hoping you can give me some advice,thanks!
When I add the security.oauth2.resource.filter-order=3,my .authorizeRequests().anyRequest().authenticated() in SecurityConfiguration doesn't work.When I hit / endpoint the chrome doesn't redirect to login page.
But if when I remove the security.oauth2.resource.filter-order=3 OAuth client will redirect to login page even client has get the access code .
My demo code is here: https://github.com/liuyatao/demo-auth
SecurityConfiguration is like this
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
web.debug(true);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().and()
.authorizeRequests().anyRequest().authenticated();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN")
.and().withUser("user").password("user").roles("USER");
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
My OAuth2Configuraton is like this
@Configuration
public class OAuth2Configuration {
@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/hello/").permitAll()
.antMatchers("/secure/**").authenticated();
}
}
@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints
.tokenStore(tokenStore())
.authenticationManager(authenticationManager);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("demo")
.scopes("read", "write")
.authorizedGrantTypes("password", "refresh_token","authorization_code")
.redirectUris("http://localhost:8082/client/myInfor")
.secret("demo");
}
}
How can i deal with this problem? Thanks !
@liuyatao These kind of problems are related with the ordering of security configuration classes. I'd suggest to take a closer look at my previous comment and the linked sample app.
@vpavic Hi I have fixed my problem.No need to add @order.I forgot to add antMatcher in my ResoureServerConfiguration . I also push the code to github
I've found the best way to debug these issues is to set debug=true and watch the printing of the security filter chain.
Since this ticket is OBE (release notes) and not a bug per-se I'm going to close it.
Most helpful comment
@vpavic and it works now. Seems that my
WebSecurityConfigand ordering was the issue in general. The filter order is not the issue for me, but rather my own configuration. Everything now works as expected. This works for me now, and it's clear that this is not a bug but pilot error. I'm not sure if @jzampieron might have a similar issue with his config as well.Thanks a million @vpavic , hit me up for a beer or three if you're ever in the Boston area!