Khoda
Khoda

Reputation: 953

Spring Security Authentication issue: HTTP 401

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.

Upvotes: 0

Views: 1352

Answers (1)

john koo
john koo

Reputation: 221

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

Upvotes: 1

Related Questions