Spring Boot OAuth 2.0 UserDetails user not found

I am new to Spring Boot and I am trying to configure OAuth 2.0. The problem I'm currently facing is that I keep getting the following message when I try to request an access token:

{"error": "invalid_grant", "error_description": "Bad credentials"}

An error message in the Spring Boot console indicates that the user cannot be found.

: authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider: User 'stromero' not found: Returning a cached instance of singleton bean 'authenticationAuditListener'

I implemented a user user that was already stored in the database using JPA, I can’t understand why Spring Security cannot find this user, this may be a problem with my logic or configuration. If someone with a lot of experience can look at my code and possibly direct me in the right direction, this will be very helpful.

This is an HTTP request:

POST / oauth / token HTTP / 1.1 Host: localhost: 8181 Authorization: Primary YnJvd3NlcjpzZWNyZXQ = Cache-Control: no-cache Content-Type: application / x-www-form-urlencoded username = stromero & password = password & client_id = browser & client_secret = secret & grant_type = password

These are the classes that I used to implement my user user and OAuth 2.0

@Repository public interface UserRepository extends CrudRepository<CustomUser, String> { public CustomUser findByUsername(String name); } 

Below is the user user I created

 @Entity @Table (name = "custom_user") public class CustomUser { @Id @Column(name = "id", nullable = false, updatable = false) @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; @Column(name = "username", unique=true, nullable = false) private String username; @Column(name = "password", nullable = false) private String password; @ElementCollection private List<String> roles = new ArrayList<>(); public List<String> getRoles() { return roles; } public void setRoles(List<String> roles) { this.roles = roles; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } 

The following is a user data service that reads user information from a database and returns it as a UserDetails object.

 @Service @Transactional(readOnly = true) public class CustomUserDetailsService implements UserDetailsService { @Autowired private UserRepository userRepository; @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { CustomUser customUser = userRepository.findByUsername(s); boolean enabled = true; boolean accountNonExpired = true; boolean credentialsNonExpired = true; boolean accountNonLocked = true; return new User( customUser .getUsername(), customUser .getPassword().toLowerCase(), enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, getAuthorities(customUser.getRoles())); } public Collection<? extends GrantedAuthority> getAuthorities(List<String> roles) { List<GrantedAuthority> authList = getGrantedAuthorities(roles); return authList; } public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles) { List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); for (String role : roles) { authorities.add(new SimpleGrantedAuthority(role)); } return authorities; } } 

Below is a data structure that contains both UserDetailsService and ClientDetailsService

 public class ClientAndUserDetailsService implements UserDetailsService, ClientDetailsService { private final ClientDetailsService clients; private final UserDetailsService users; private final ClientDetailsUserDetailsService clientDetailsWrapper; public ClientAndUserDetailsService(ClientDetailsService clients, UserDetailsService users) { super(); this.clients = clients; this.users = users; clientDetailsWrapper = new ClientDetailsUserDetailsService(this.clients); } @Override public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException { return clients.loadClientByClientId(clientId); } @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { UserDetails user = null; try{ user = users.loadUserByUsername(username); }catch(UsernameNotFoundException e){ user = clientDetailsWrapper.loadUserByUsername(username); } return user; } } 

Below is my configuration for OAuth 2.0 using Spring Boot

  @Configuration public class OAuth2SecurityConfiguration { @Configuration @EnableWebSecurity protected static class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Autowired protected void registerAuthentication( final AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService); } } @Configuration @EnableResourceServer protected static class ResourceServer extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.csrf().disable(); http.authorizeRequests().antMatchers("/oauth/token").anonymous(); // Require all GET requests to have client "read" scope http.authorizeRequests().antMatchers(HttpMethod.GET, "/**") .access("#oauth2.hasScope('read')"); // Require all POST requests to have client "write" scope http.authorizeRequests().antMatchers(HttpMethod.POST,"/**") .access("#oauth2.hasScope('write')"); } } @Configuration @EnableAuthorizationServer @Order(Ordered.LOWEST_PRECEDENCE - 100) protected static class AuthorizationServer extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager authenticationManager; private ClientAndUserDetailsService combinedService; public AuthorizationServer() throws Exception { ClientDetailsService clientDetailsService = new InMemoryClientDetailsServiceBuilder() .withClient("browser") .secret("secret") .authorizedGrantTypes("password") .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") .scopes("read","write") .resourceIds("message") .accessTokenValiditySeconds(7200) .and() .build(); // Create a series of hard-coded users. UserDetailsService userDetailsService = new CustomUserDetailsService(); combinedService = new ClientAndUserDetailsService(clientDetailsService, userDetailsService); } @Bean public ClientDetailsService clientDetailsService() throws Exception { return combinedService; } @Bean public UserDetailsService userDetailsService() { return combinedService; } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.withClientDetails(clientDetailsService()); } } } 

Below is my pom.xml file

  <properties> <tomcat.version>8.0.8</tomcat.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <!-- Postgres JDBC Driver --> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>9.2-1002-jdbc4</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- Hibernate validator --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> <version>2.0.3.RELEASE</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>17.0</version> </dependency> </dependencies> 
+5
source share
3 answers

Yes, I had the same problem ... I wanted to use the JPA UserDetailsService , but the same problem - the user could not be found ... they were finally allowed, thanks to Dave Syer OAuth2 samples on GitHub.

The problem seems to be with the authenticationManager instance that was automatically added to the @EnableAuthorizationServer AuthorizationServer class. The AuthenticationManager is autwired there and seems to be initialized by default to the DAOAuthenticationProvider , and for some reason it does not use the user JPA UserDetailsService , we initialize the authenticationManager using WebSecurityConfiguration .

In the Dave Syer samples, the authenticationManager appears as a bean in the WebSecurityConfiguration :

  @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } 

then in AuthorizationServer we will automatically authenticate the Manager as follows:

  @Autowired @Qualifier("authenticationManagerBean") private AuthenticationManager authenticationManager; 

As soon as I did this, I finally managed to authenticate my user against my JPA client user repository.

+17
source

I ran into the same problem and spent hours investigating the matter. As a workaround, if you are using Spring Boot version 1.1.8.RELEASE, go to 1.0.2.RELEASE. Everything went well, but I have not yet investigated the causes of the compatibility issue with Spring Boot version 1.1.8.RELEASE.

+1
source

InitializeUserDetailsBeanManagerConfigurer has default order as

 static final int DEFAULT_ORDER = Ordered.LOWEST_PRECEDENCE - 5000; 

So, it initializes the DaoAuthenticationProvider before the user.

 @Order(-5001) public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { ... } 
0
source

Source: https://habr.com/ru/post/1204071/


All Articles