I am using Spring Boot, Spring Security, OAuth2 and JWT to authenticate my application, but I keep getting this nasty error and I don\'t have any idea what is wrong. My
When oauth2 dependecncies moved to cloud, I started facing this issue. Earlier it was part of security framework :
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
Now it is part of cloud framework :
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
So if you are using cloud dependency (Finchley.RELEASE) then you may need to encode the secret like below :
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("clientapp")
.authorizedGrantTypes("password","refresh_token")
.authorities("USER")
.scopes("read", "write")
.resourceIds(RESOURCE_ID)
.secret(passwordEncoder.encode("SECRET"));
}
Please check if your method UserDetails loadUserByUsername(String username)
returns valid UserDetail
object. If Returned object is null / object with invalid values then also you will see this error.
The best way to identify this problem "Encoded password does not look like BCrypt" is setup a break porint in class org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder. And then check the root cause for the warnning.
if (!BCRYPT_PATTERN.matcher(encodedPassword).matches()) {
logger.warn("Encoded password does not look like BCrypt");
return false;
}
Can you double check your client secret is encoded?
@Override
public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
configurer
.inMemory()
.withClient(clientId)
.secret(passwordEncoder.encode(clientSecret))
.authorizedGrantTypes(grantType)
.scopes(scopeRead, scopeWrite)
.resourceIds(resourceIds);
}
The PasswordEncoder should be set like this:
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
Update field client_secret
in table oauth_client_details
with BCryptPasswordEncoder
in case you migrate spring boot from 1x to 2x. To encode secret use:
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String password = "12345678";
String encodedPassword = passwordEncoder.encode(password);
System.out.println();
System.out.println("Password is : " + password);
System.out.println("Encoded Password is : " + encodedPassword);
System.out.println();
boolean isPasswordMatch = passwordEncoder.matches(password, encodedPassword);
System.out.println("Password : " + password + " isPasswordMatch : " + isPasswordMatch);