0

I've encountered a bizarre situation using spring security. Having used:

 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE</version> </parent> 

With following simple security configuration:

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { UserDetails user = User.builder().username("1").password("1").roles("USER").build(); auth.inMemoryAuthentication().withUser(user).passwordEncoder(new BCryptPasswordEncoder()); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable().authorizeRequests().antMatchers("/inquiry").authenticated().anyRequest().permitAll().and() .httpBasic(); } } 

I constantly get the 401 Http Status code. But I dig deeper into the code and I've realized that in the spring security core there is a minor issue. The class DaoAuthenticationProvider tries to check if the provided password matches the actual credential with password encoder(in my case BCrypt) in hand. So

if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) 

But in the encoder, the method signature of matches is:

public boolean matches(CharSequence rawPassword, String encodedPassword) 

So the authentication fails.

1
  • I followed this and it solved my problem. Commented Sep 29, 2018 at 9:15

1 Answer 1

1

When you use in-memory authentication with BCrypt in your security configuration, you need to encrypt the password string first.

So you can try

@Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { // First encrypt the password string String encodedPassword = passwordEncoder().encode("1"); // Set the password UserDetails user = User.builder() .username("1") .password(encodedPassword) .roles("USER") .build(); // Use in-memory authentication with BCryptEncoder auth.inMemoryAuthentication() .withUser(user) .passwordEncoder(passwordEncoder()); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } 
Sign up to request clarification or add additional context in comments.

2 Comments

Nice one! You can drop explicit setup at passwordEncoder(passwordEncoder()) because you are already providing @Bean PasswordEncoder and Spring will take care of injecting it as default one. BTW, it is not a good idea to encode passwords from plaintext at runtime. Provide only encoded passwords in source code!
Nice suggestion @TheStrikeBone. The in-memory authentication is not appropriate for production env. So I provided the solution according to the question. As you mentioned encoding password at runtime is a bad practice.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.