Spring Security 5: Missing PasswordEncoder id for id null

I am migrating from Spring Boot 1.4.9 to Spring Boot 2.0 as well as Spring Security 5, and I am trying to authenticate through OAuth 2. But I get this error:

java.lang.IllegalArgumentException: no PasswordEncoder id for id "null

From the Spring Security 5 documentation , I find out that the password storage format will change.

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

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

However, this gave me the error below:

Encrypted password is not like BCrypt

Therefore, I am updating the encoder according to Spring Security 5 so that:

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

Now, if I can see the password in the database, it is stored as

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

, , , , :

java.lang.IllegalArgumentException: PasswordEncoder "null

, Stackoverflow:

, , answerd:

. , UserDetailsService.

Spring Security 5 , :

DelegatingPasswordEncoder.setDefaultPasswordEncoderForMatches(PasswordEncoder)

, ? PasswordEncoder bean, , :

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

MyWebSecurity

@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
@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);
    }
}

, . , , .

+32
6

ClientDetailsServiceConfigurer, .

.secret("{noop}secret")
+54

, - - .

, - .

, , .

:


WebSecurityConfigurerAdapter :

@SuppressWarnings("deprecation")
@Bean
public static NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}

, , , .


, PasswordEncoder BCryptPasswordEncoder BCryptPasswordEncoder :

// Create an encoder with strength 16
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16);
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
+7

.password("{noop}password") .

:

auth.inMemoryAuthentication()
        .withUser("admin").roles("ADMIN").password("{noop}password");
+4

, Spring , , bcrypt, scrypt, pbkdf2 .., , , . , defaultPasswordEncoderForMatches. DelegatingPasswordEncoder.class, , . defaultPasswordEncoderForMatches .

@Bean(name="myPasswordEncoder")
public PasswordEncoder getPasswordEncoder() {
        DelegatingPasswordEncoder delPasswordEncoder=  (DelegatingPasswordEncoder)PasswordEncoderFactories.createDelegatingPasswordEncoder();
        BCryptPasswordEncoder bcryptPasswordEncoder =new BCryptPasswordEncoder();
    delPasswordEncoder.setDefaultPasswordEncoderForMatches(bcryptPasswordEncoder);
    return delPasswordEncoder;      
}

DefaultPasswordEncoderForMatches . .

@Bean
    @Autowired  
    public DaoAuthenticationProvider getDaoAuthenticationProvider(@Qualifier("myPasswordEncoder") PasswordEncoder passwordEncoder, UserDetailsService userDetailsServiceJDBC) {
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
        daoAuthenticationProvider.setUserDetailsService(userDetailsServiceJDBC);
        return daoAuthenticationProvider;
    }
+1

BCrypt

In my case, there was a mismatch in the strength of BCryptPasswordEncoder used by the default constructor (10), since the pwd hash was created with strength 4. Therefore, I set the strength explicitly.

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

also my Spring Security 5.1.6 version and it works great with BCryptPasswordEncoder

0
source

This error can occur if you mistakenly forget to use the @Bean annotation in your business logic.

  @Bean 
  public AuthenticationProvider authProvider() {
      DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
      provider.setUserDetailsService(userDetailsService);
      provider.setPasswordEncoder(NoOpPasswordEncoder.getInstance()); 
      return provider; 
  }
-1
source

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


All Articles