Default Password Encoder in Spring Security 5

1. Overview

In Spring Security 4, it was possible to store passwords in plain text using in-memory authentication.

A major overhaul of the password management process in version 5 has introduced a more secure default mechanism for encoding and decoding passwords. This means that if your Spring application stores passwords in plain text, upgrading to Spring Security 5 may cause problems.

In this short tutorial, we’ll describe one of those potential problems and demonstrate a solution.

2. Spring Security 4

We’ll start by showing a standard security configuration that provides simple in-memory authentication (valid for Spring 4):

@Configuration
public class InMemoryAuthWebSecurityConfigurer 
  extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) 
      throws Exception {
        auth.inMemoryAuthentication()
          .withUser("spring")
          .password("secret")
          .roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
          .antMatchers("/private/**")
          .authenticated()
          .antMatchers("/public/**")
          .permitAll()
          .and()
          .httpBasic();
    }
}

This configuration defines authentication for all /private/ mapped methods and public access for everything under /public/.

If we use the same configuration under Spring Security 5, we’ll get the following error:

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

The error tells us that the given password couldn’t be decoded since no password encoder was configured for our in-memory authentication.

3. Spring Security 5

We can fix this error by defining a DelegatingPasswordEncoder with the PasswordEncoderFactories class.

We use this encoder to configure our user with the AuthenticationManagerBuilder:

@Configuration
public class InMemoryAuthWebSecurityConfigurer 
  extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) 
      throws Exception {
        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        auth.inMemoryAuthentication()
          .withUser("spring")
          .password(encoder.encode("secret"))
          .roles("USER");
    }
}

Now, with this configuration, we’re storing our in-memory password using BCrypt in the following format:

{bcrypt}$2a$10$MF7hYnWLeLT66gNccBgxaONZHbrSMjlUofkp50sSpBw2PJjUqU.zS

Although we can define our own set of password encoders, it’s recommended to stick with the default encoders provided in PasswordEncoderFactories.

3.2. NoOpPasswordEncoder

If, for any reason, we don’t want to encode the configured password, we can make use of the NoOpPasswordEncoder.

To do so, we simply prefix the passphrase we provide to the password() method with the {noop} identifier:

@Configuration
public class InMemoryNoOpAuthWebSecurityConfigurer 
  extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) 
      throws Exception {
        auth.inMemoryAuthentication()
          .withUser("spring")
          .password("{noop}secret")
          .roles("USER");
    }
}

This way, Spring Security will use the NoOpPasswordEncoder under the hood when it compares the password provided by the user with the one we configured above.

Note, however, that we should never use this approach on the production application! As the official documentation says, the NoOpPasswordEncoder has been deprecated to indicate that it’s a legacy implementation, and using it is considered insecure.

3.3. Migrating Existing Passwords

We can update existing passwords to the recommended Spring Security 5 standards by:

  • Updating plain text stored passwords with their value encoded:
String encoded = new BCryptPasswordEncoder().encode(plainTextPassword);

Prefixing hashed stored passwords with their known encoder identifier:

{bcrypt}$2a$10$MF7hYnWLeLT66gNccBgxaONZHbrSMjlUofkp50sSpBw2PJjUqU.zS
{sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0

Requesting users to update their passwords when the encoding-mechanism for stored passwords is unknown

4. Conclusion

In this quick example, we updated a valid Spring 4 in-memory authentication configuration to Spring 5 using the new password storage mechanism.

As always, you can find the source code over on the GitHub project.

Related posts:

Java Program to Implement PrinterStateReasons API
Number Formatting in Java
Java Program to Implement the Alexander Bogomolny’s UnOrdered Permutation Algorithm for Elements Fro...
Finding Max/Min of a List or Collection
Java Program to Find SSSP (Single Source Shortest Path) in DAG (Directed Acyclic Graphs)
Java Program to Check Whether a Given Point is in a Given Polygon
Câu lệnh điều khiển vòng lặp trong Java (break, continue)
Jackson – JsonMappingException (No serializer found for class)
Introduction to Using Thymeleaf in Spring
Runnable vs. Callable in Java
Java Program to Implement the Schonhage-Strassen Algorithm for Multiplication of Two Numbers
Handling Errors in Spring WebFlux
Java Program to Implement Disjoint Set Data Structure
Migrating from JUnit 4 to JUnit 5
Using the Map.Entry Java Class
Java Program to Find MST (Minimum Spanning Tree) using Kruskal’s Algorithm
Java Program to Implement SimpeBindings API
New Features in Java 12
Debugging Reactive Streams in Java
Java Program to Perform Searching in a 2-Dimension K-D Tree
Java Program to Perform Searching Using Self-Organizing Lists
Java Program to Implement Iterative Deepening
ETL with Spring Cloud Data Flow
Java Program to Perform Quick Sort on Large Number of Elements
Servlet 3 Async Support with Spring MVC and Spring Security
wait() and notify() Methods in Java
Spring Data JPA and Null Parameters
Java Program to Find the Number of Ways to Write a Number as the Sum of Numbers Smaller than Itself
The Registration API becomes RESTful
Java Program to Implement RenderingHints API
New in Spring Security OAuth2 – Verify Claims
Java Program to Implement CopyOnWriteArrayList API