We’ll see a warning message “o.s.s.c.bcrypt.BCryptPasswordEncoder : Encoded password does not look like BCrypt” in the spring boot console logs. We’ll see a pattern that the user has not been able to access whatever the password entered. We’re going to see this warning message in the post.
If users of the application attempt to login with a valid username and password, the spring boot security module will not allow access. Authentication failure will always be seen. If you check in the spring boot console log, you will not see any error message. You’ll see this warning message instead.
2020-02-21 08:51:53.543 WARN 9312 --- [ main] o.s.s.c.bcrypt.BCryptPasswordEncoder : Encoded password does not look like BCrypt
Root Cause
In the spring boot application, the spring boot security module is configured and authentication & authorization is enabled. The BCryptPasswordEncoder is used to encrypt and verify the password.
When the password is stored using the BCryptPasswordEncoder, the password is encoded. The encoded password includes 60 characters and should be in the regular expression format below. If the encoded password varies from the regular expression format, this alert will be shown in the console log.
The result is that the user is not authenticated whatever the password is entered.
Encoded Password Format
\\A\\$2(a|y|b)?\\$(\\d\\d)\\$[./0-9A-Za-z]{53}
Sample Password
Password is : password
Encoded Password is : $2a$10$e59rGaFvpijWXLh03j0aZOzBYQNrIRIjlB8sGwLvBL35fecblsW1m
How to reproduce this issue
In the spring boot application, add the spring boot security module as a dependency in the pom.xml file. Use the BCryptPasswordEncoder to construct a correct encoded password. Add a few junk characters to the encoded password or delete any characters from the encoded password. Now check your password with a changed encoded password. The warning message will be shown in the console log.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.yawintutor</groupId>
<artifactId>Spring-Application</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringBootSecurityPasswordEncoder</name>
<description>Spring Boot Project</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
SpringBootSecurityPasswordEncoderApplication.java
package com.yawintutor;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@SpringBootApplication
public class SpringBootSecurityPasswordEncoderApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootSecurityPasswordEncoderApplication.class, args);
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String password = "password";
String encodedPassword = passwordEncoder.encode(password);
System.out.println();
System.out.println("Password is : " + password);
System.out.println("Encoded Password is : " + encodedPassword);
System.out.println("Invalid Password is : " + encodedPassword + "junk");
System.out.println();
boolean isPasswordMatch = passwordEncoder.matches(password, encodedPassword+"junk");
System.out.println("Password : " + password + " isPasswordMatch : " + isPasswordMatch);
}
}
Solution 1
The length of the encoded password should be 60 characters. Check the encoded password length. If the length of the encoded password is not 60 characters, the encoded password is wrongly created or stored. Tell the user to reset the password or generate a dummy password and encrypt it with the BCryptPasswordEncoder. Check this page to encrypt your password. https://www.yawintutor.com/encode-decode-using-bcryptpasswordencoder-in-spring-boot-security/
Solution 2
This encoded password would match the regular expression. If the format is different, the password will be modified or created using a different password encoder other than the BCryptPasswordEncoder. Identify which password encoder to use and configure the same. If the application uses BCryptPasswordEncoder, reset the password or generate a dummy password and encrypt. Check this page to encrypt your password. https://www.yawintutor.com/encode-decode-using-bcryptpasswordencoder-in-spring-boot-security/
Solution 3
If the encoded password length is 60 characters long and follows the regular expression as mentioned above, then use the following example to verify your password with the encoded password. If the example below is returned correctly, this warning message will not be shown.
package com.yawintutor;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@SpringBootApplication
public class SpringBootSecurityPasswordEncoderApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootSecurityPasswordEncoderApplication.class, args);
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String password = "password";
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);
}
}