Refresh token call fails using spring security an oauth2 with error: UserDetailsService is required
java, spring, spring-oauth2, spring-security, spring-security-oauth2
Solution
Authorization server endpoint needs `UserDetailsService`. In your `OAuth2Config` class configure user details service like the following:
@Autowired
private UserDetailsService userDetailsService;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore);
endpoints.userDetailsService(userDetailsService);
endpoints.authenticationManager(authenticationManager)
.approvalStoreDisabled();
}
You can also configure it in `WebSecurityConfigurerAdapter`:
@Autowired
private AuthorizationServerEndpointsConfiguration endpoints;
@Override
protected void configure(HttpSecurity http) throws Exception {
if (!endpoints.getEndpointsConfigurer().isUserDetailsServiceOverride()) {
UserDetailsService userDetailsService = http.getSharedObject(UserDetailsService.class);
endpoints.getEndpointsConfigurer().userDetailsService(userDetailsService);
}
// @formatter:off
http
.authorizeRequests()
.antMatchers("/myRest/events/**", "/events/**", "/events", "/myRest/events").permitAll()
.antMatchers("/login.jsp", "/login").permitAll()
.and()
.csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize")).disable()
.csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/myRest/events")).disable()
.sessionManagement().sessionFixation().none();
// @formatter:on
}
Problem
I am using Spring Security OAuth2 for authorizations. When trying to refresh the token I get an error: `UserDetailsService is required` (interestingly I get this error only on unix machines and not on windows). I am using Spring OAuth2 version 2.0.7. For some reason the `AuthenticationManager` in the `DefaultTokenService` is not empty and it tries to authenticate the user to check if he still exists. I think it gets initialized because of some spring security vs. spring oauth2 configuration problems. I am not using any custom `UserDetailsService`, hence it should not authenticate the users at this point. However, when I debug it I see that it tries to use one from the `WebSecurityConfigurerAdapter` and gets to this error. Even if I provide my custom dummy `UserDetailsService`, it is not using that one, but tries to use the other one, which is null. Am I missing here something? I can not find out why is this happening? Here is my Oauth2 configuration ``` @Configuration @EnableAuthorizationServer public class OAuth2Config extends AuthorizationServerConfigurerAdapter { @Autowired private MySpringTokenStore tokenStore; @Autowired private AuthenticationManager authenticationManager; @Autowired private MyClientDetailsServiceImpl clientDetailsService; @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.tokenStore(tokenStore); endpoints.authenticationManager(authenticationManager) .approvalStoreDisabled(); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.withClientDetails(clientDetailsService); } @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security.allowFormAuthenticationForClients(); } @Bean public TokenStore tokenStore() { return new InMemoryTokenStore(); } } ``` Here is my Spring security configuration ``` @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off http .authorizeRequests() .antMatchers("/myRest/events/**", "/events/**", "/events", "/myRest/events").permitAll() .antMatchers("/login.jsp", "/login").permitAll() .and() .csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize")).disable() .csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/myRest/events")).disable() .sessionManagement().sessionFixation().none(); // @formatter:on } @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/index*", "/myRest/events/**", "/events/**", "/myRest/events", "/events", "/swagger/**", "/kibana/**", "/elastic/**", "/version/**", "/api-docs/**", "/js/**", "/oauth/uncache_approvals", "/oauth/cache_approvals"); } } ```