Spring OAuth2 401 Unauthorized when trying to obtain access token at oauth/token endpoint

3.3k views Asked by At

I am new to OAuth2 and I am receiving a 401 Unauthorized when trying to obtain my access token through a password grant flow. My UserDetailsService is implemented with a MySQL database backend, but I never hit the loadUserByUsername method before I receive my 401 Unauthorized message, so I think it may be a problem with my OAuth2 configuration. My AuthorizationConfigurerAdapter is as follows:

...imports

@Configuration

@EnableAuthorizationServer
public class AuthorizationServerConfig extends     
AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

    @Value("${signing-key:oui214}")
    private String signingKey;

    public AuthorizationServerConfig() {
        super();
    }

   // beans

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        final JwtAccessTokenConverter jwtAccessTokenConverter = new               
        JwtAccessTokenConverter();
        jwtAccessTokenConverter.setSigningKey(signingKey);
        return jwtAccessTokenConverter;
    }

    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }

    @Bean
    @Primary
    public DefaultTokenServices tokenServices() {
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setTokenStore(tokenStore());
        return tokenServices;
    }

    // config

    @Override
    public void configure(final ClientDetailsServiceConfigurer clients)  
    throws Exception {
        // @formatter:off
        clients.inMemory()
               .withClient("password-flow-client")
               .secret("publicpass")
               .authorizedGrantTypes("password")
               .scopes("qlc-webapp")
               .accessTokenValiditySeconds(3600 * 12);
               // @formatter:on
    }

    @Override
    public void configure(final AuthorizationServerEndpointsConfigurer    
    endpoints) {

         // @formatter:off
         endpoints.tokenStore(tokenStore()).
         tokenEnhancer(tokenEnhancerChain).
         authenticationManager(authenticationManager);

         endpoints.tokenStore(tokenStore()).
         authenticationManager(authenticationManager).
         userDetailsService(userDetailsService).
         allowedTokenEndpointRequestMethods(HttpMethod.GET,  
         HttpMethod.POST).accessTokenConverter(accessTokenConverter());
         // @formatter:on
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) 
    throws Exception {
        security.checkTokenAccess("permitAll()");
        super.configure(security);
    }

}

My ResourceConfigurerAdapter is as follows:

...imports


@Configuration
@EnableResourceServer
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
@ComponentScan({ "org.quickloanconnect.spring.security" })
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Value("${signing-key:oui214}")
    private String signingKey;

    public ResourceServerConfig() {
        super();
    }

    // global security concerns

    @Bean
    public AuthenticationProvider authProvider() {
        final DaoAuthenticationProvider authProvider = new   
        DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService);
        return authProvider;
    }

    @Autowired
    public void configureGlobal(final AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(authProvider());
    }

    // http security concerns

    @Override
    public void configure(final HttpSecurity http) throws Exception {
        // @formatter:off
        http.
        authorizeRequests().
        // antMatchers("/oauth/token").permitAll().
        anyRequest().authenticated().and().

        sessionManagement().
        sessionCreationPolicy(SessionCreationPolicy.STATELESS).
        and().
        csrf().disable();
        // @formatter:on
   }

}

MyUserDetailsService implementation of UserDetailsService

@Component
public final class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private IUsersService userService;

    public MyUserDetailsService() {
        super();
    }

    @Override
    public final UserDetails loadUserByUsername(final String username) {
        Preconditions.checkNotNull(username);

        final User user = userService.findUserByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("Username was not found: " + 
            username);
        }

        return new  
        org.springframework.security.core.userdetails.User(username, 
        user.getPassword(), Lists.newArrayList());
}

I had this working with inMemory user setup (no user details service at that time), but when switching to the userDetailsService backend and eliminating my in memory user, my configuration does not seem to work and I get 401 Unauthorized. Are there changes in my configuration that I need to do now that I am using UserDetailsService? Am I missing something?

0

There are 0 answers