Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security 5 : There is no PasswordEncoder mapped for the id "null"

I am migrating from Spring Boot 1.4.9 to Spring Boot 2.0 and also to Spring Security 5 and I am trying to do authenticate via OAuth 2. But I am getting this error:

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

From the documentation of Spring Security 5, I get to know that storage format for password is changed.

In my current code I have created my password encoder bean as:

@Bean public BCryptPasswordEncoder passwordEncoder() {     return new BCryptPasswordEncoder(); } 

However it was giving me below error:

Encoded password does not look like BCrypt

So I update the encoder as per the Spring Security 5 document to:

@Bean public PasswordEncoder passwordEncoder() {     return PasswordEncoderFactories.createDelegatingPasswordEncoder(); } 

Now if I can see password in database it is storing as

{bcrypt}$2a$10$LoV/3z36G86x6Gn101aekuz3q9d7yfBp3jFn7dzNN/AL5630FyUQ 

With that 1st error gone and now when I am trying to do authentication I am getting below error:

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

To solve this issue I tried all the below questions from Stackoverflow:

  • Spring Boot PasswordEncoder Error

  • Spring Oauth2. Password encoder is not set in DaoAuthenticationProvider

Here is a question similar to mine but not answerd:

  • Spring Security 5 - Password Migration

NOTE: I am already storing encrypted password in database so no need to encode again in UserDetailsService.

In the Spring security 5 documentation they suggested you can handle this exception using:

DelegatingPasswordEncoder.setDefaultPasswordEncoderForMatches(PasswordEncoder)

If this is the fix then where should I put it? I have tried to put it in PasswordEncoder bean like below but it wasn't working:

DelegatingPasswordEncoder def = new DelegatingPasswordEncoder(idForEncode, encoders); def.setDefaultPasswordEncoderForMatches(passwordEncoder); 

MyWebSecurity class

@Configuration @EnableWebSecurity public class SecurityConfiguration extends WebSecurityConfigurerAdapter {      @Autowired     private UserDetailsService userDetailsService;      @Bean     public PasswordEncoder passwordEncoder() {         return PasswordEncoderFactories.createDelegatingPasswordEncoder();     }      @Autowired     public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {         auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());     }      @Override     public void configure(WebSecurity web) throws Exception {          web                 .ignoring()                 .antMatchers(HttpMethod.OPTIONS)                 .antMatchers("/api/user/add");     }      @Override     @Bean     public AuthenticationManager authenticationManagerBean() throws Exception {         return super.authenticationManagerBean();     } } 

MyOauth2 Configuration

@Configuration @EnableAuthorizationServer protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {      @Bean     public TokenStore tokenStore() {         return new InMemoryTokenStore();     }      @Autowired     @Qualifier("authenticationManagerBean")     private AuthenticationManager authenticationManager;       @Bean     public TokenEnhancer tokenEnhancer() {         return new CustomTokenEnhancer();     }      @Bean     public DefaultAccessTokenConverter accessTokenConverter() {         return new DefaultAccessTokenConverter();     }      @Override     public void configure(AuthorizationServerEndpointsConfigurer endpoints)             throws Exception {         endpoints                 .tokenStore(tokenStore())                 .tokenEnhancer(tokenEnhancer())                 .accessTokenConverter(accessTokenConverter())                 .authenticationManager(authenticationManager);     }      @Override     public void configure(ClientDetailsServiceConfigurer clients) throws Exception {         clients                 .inMemory()                 .withClient("test")                 .scopes("read", "write")                 .authorities(Roles.ADMIN.name(), Roles.USER.name())                 .authorizedGrantTypes("password", "refresh_token")                 .secret("secret")                 .accessTokenValiditySeconds(1800);     } } 

Please guide me with this issue. I have spend hours to fix this but not able to fix.

like image 524
Jimmy Avatar asked Apr 04 '18 14:04

Jimmy


People also ask

What is PasswordEncoder in Spring Security?

We use the PasswordEncoder that is defined in the Spring Security configuration to encode the password. In this example, the passwords are encoded with the bcrypt algorithm because we set the PasswordEncoder as the password encoder in the configuration. The code just saves the new user to the database.

What can I use instead of NoOpPasswordEncoder?

Class NoOpPasswordEncoder. Deprecated. This PasswordEncoder is not secure. Instead use an adaptive one way function like BCryptPasswordEncoder, Pbkdf2PasswordEncoder, or SCryptPasswordEncoder.


1 Answers

When you are configuring the ClientDetailsServiceConfigurer, you have to also apply the new password storage format to the client secret.

.secret("{noop}secret") 
like image 98
Edwin Diaz Avatar answered Sep 22 '22 08:09

Edwin Diaz