I'm trying to configure an OAuth2 server that will be capable to complete the basic OAuth2 flows (see here for examples).
Apologies for the long question
My first attempt is to be able to perform an authorization_code flow.
I have the following configuration:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig
extends WebSecurityConfigurerAdapter {
....
@Inject
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
...
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin().loginPage("/login").permitAll()
.and()
.requestMatchers().antMatchers("/login", "/oauth/authorize", "/oauth/confirm_access")
.and()
.authorizeRequests().anyRequest().authenticated();
}
...
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
My Server configuration
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorServerConfig
extends AuthorizationServerConfigurerAdapter {
@Inject
private TokenStore tokenStore;
@Inject
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.tokenStore(tokenStore)
.authenticationManager(authenticationManager);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
.allowFormAuthenticationForClients()
.checkTokenAccess("authenticated()");
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
.inMemory()
.withClient("foo")
.secret("foo")
.authorizedGrantTypes("authorization_code","password", "refresh_token")
.scopes(new String[] { "read", "write" })
}
And indeed my authorization code flow works ok! Problem start when I try to do a password flow as follows:
POST localhost:8200/oauth/token
Content-Type: application/x-www-form-urlencoded
Accept:application/json
Authorization:Basic Zm9vOmZvbw=="
username=admin&password=admin&grant_type=password&scope=read%20write&client_secret=foo&client_id=foo&
My problem is that the Authorization header is ignored, whether it is there or not the result is the same, it gives me back the access_token and refresh_token
If I try to enable the basic authentication as follows, enable ClientUserDetailsService, reading clients from database JDBC:
public class SecurityConfig
extends WebSecurityConfigurerAdapter {
....
@Bean
public ClientDetailsUserDetailsService clientDetailsUserDetailsService(ClientDetailsService clientDetailsService){
// JDBC clientDetailsService
return new ClientDetailsUserDetailsService(clientDetailsService);
}
@Inject
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(clientDetailsUserDetailsService());
}
...
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
DaoAuthenticationProvider p = new DaoAuthenticationProvider();
p.setUserDetailsService(userDetailsService);
p.setPasswordEncoder(passwordEncoder());
return new ProviderManager(Lists.newArrayList(p));
// return super.authenticationManagerBean();
}
}
Now what I have achieved is to have the basic authentication working properly BUT i loose the authorization_code flow since the basic authentication now it is done against the clientid and secret and NOT the user's actual credentials
Am I missing something? How can I have both flows? Please help, I'm struggling for some days now.
Some Similar questions, but without any luck: