elvis
elvis

Reputation: 1178

Why this Spring Security implementation is checking only for the password and not for the username?

I'm working on a simple Spring Boot app using Spring Security. And I hardcoded an username and password, but the problem is that I can login with any username, only the password is checked by Spring Security.

This is the code:

@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    public final MyUserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

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

MyUserDetailsService class:

@Service
public class MyUserDetailsService implements UserDetailsService {

    private static final String USERNAME = "john";
    private static final String PASSWORD = "$2a$10$5yPLXyd0J2TEHhsbD3Azjumpn6OePKsiV1XPpFaZfytT33mRAn3N6";

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        return new org.springframework.security.core.userdetails
                .User(USERNAME, PASSWORD, new ArrayList<>());
    }
}

Rest Controller class:

@RestController
public class ApiController {

    @GetMapping("/hello")
    public String sendMoney() {
        return "Hello World!";
    }
}

I hardcoded the username "john" and password "test" encrypted with BCrypt. But the problem is that I can login with any username, only the password should be "test". Can somebody explain me why? Why Spring Security is checking only the password to be "test", but it doesn't check for the username to be "john"? Any feedback will be apreciated. Thank you!

Upvotes: 1

Views: 769

Answers (2)

Grzegorz Oledzki
Grzegorz Oledzki

Reputation: 24251

You seem to ignore the argument s to:

    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {

so in other words - for whatever user details the code is asked to retrieve, it retrieves the hard-coded ones. User "notjohn"? Sure we have it. User "notexisting"? We also have it, etc.

I guess your intention is to have a check if s equals to "john" and only return the hard-coded user details if the requested username is "john".

Upvotes: 1

Serge Ballesta
Serge Ballesta

Reputation: 148890

This is by design. UserDetailsService.loadUserByUsername(String user) is expected to provide the record corresponding to user. It is acceptable to use a hardcoded record, but then you are responsable to control that the user name is correct.

But in fact, if you want SpringSecurity to test both the user name and the password, you should not implement a custom UserDetailService, but directly use a InMemoryUserDetailsManager that provides it out of the box.

Upvotes: 2

Related Questions