I'm developing an application that allows an authenticated user to create OAuth2 bearer tokens for use with APIs published by the organization. The idea is to allow the user to self generate / revoke such tokens, similar to GitHub's Personal API tokens. The user can then use the issued tokens to gain programmatic access to protected resources. In this configuration, the OAuth "Client", "Authorization Server" and the "Resource Server" belong to the organization. For now, all of these services reside in the same process.
To this end, I'm trying support the Resource Owner Password Credentials Grant type. The implementation environment consists of following:
One constraint the implementation has is that is does not have access to the stored password. This processing is delegated to an internal web service which does the actual authentication.
Because of the constraint of not having access to the stored password, the default configured DaoAuthenticationProvider
cannot be used since it requires access to the password provided by the UserDetails
object returned by the provider's UserDetailsService
.
My guess is that I will need to replace this AuthenticationProvider
with a custom implementation. However, all attempts at doing so seem to not take effect.
The following seemed to register correctly in the parent
reference of the AuthenticationManager
, but is not delegated to at runtime (due the DaoAuthenticationProvider
taking precedence):
@Configuration
public class SecurityConfig extends GlobalAuthenticationConfigurerAdapter {
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new AuthenticationProvider() {
@Override
public boolean supports(Class<?> authentication) {
// For testing this is easier, but should check for UsernamePasswordAuthentication.class
return true;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// Perform custom logic...
return authentication;
}
});
}
}
It seems no matter what I try (see references below) I always get the following two providers in ProviderManager
when the BasicAuthenticationFilter
invokes Authentication authResult = authenticationManager.authenticate(authRequest)
in its doFilter
method:
[
org.springframework.security.authentication.AnonymousAuthenticationProvider@366815e4,
org.springframework.security.authentication.dao.DaoAuthenticationProvider@5da3e311
]
I believe this may be a consequence of the AuthorizationServerSecurityConfigurer
's clientCredentialsTokenEndpointFilter
method. However, this class is marked final
and therefore cannot be customized.
Any suggestions or pointers would be greatly appreciated.
Things that I have tried / researched:
If I understand correctly, you need a custom authentication manager for users in the password grant. There is a builder method for that: AuthorizationServerEndpointsConfigurer.authenticationManager(AuthenticationManager)
. And an example of using it:
@Configuration
@EnableAuthorizationServer
protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
...