Search code examples
javaspringspring-securitymockmvc

Spring security custom UserDetails not authenticating


while experimenting around with spring boot, security, and data.

i just came across this scenario:

i use H2 in memory DB and poblate it with one user with liquibase on startup with username and password.

now i want spring security to authenticate against H2. for that purpose i have this code:

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

and im implementing the userDetails as follows:

@Override
public UserDetails loadUserByUsername(String username) {
//this works, the user with pass is pulled
    com.fix.demo.logic.user.User byUsername = 
userRepository.findByUsername(username); 
    if (byUsername == null) {
        System.out.println("No user found with username: ");
        return null; //trow ex here
    }
    User user = new User(byUsername.getUsername(),
            byUsername.getPassword(), true, true,
            true, true, getAuthorities(Collections.singletonList("user")));
    //System.out.println(user.toString());
    //System.out.println(byUsername.toString()+ "   "+byUsername.getPassword());
        return user;
    }

but my tests keep failing with

Authentication should not be null

and trying to log in will give me

bad credentials

what is necessary for my custom implementation of UserDetailsService to work?

this is the failing test:

@Test
public void loginWithValidUserThenAuthenticated() throws Exception {
    FormLoginRequestBuilder login = formLogin()
            .user("admin")
            .password("root");

    mockMvc.perform(login)
            .andExpect(authenticated().withUsername("admin"));
}

Solution

  • One of the reasons is, the password might my encoded and you need to tell spring security to use an encoder. Add the following line to the configure override.

    auth.setPasswordEncoder(passwordEncoder());
    

    define the passwordEncoder bean.

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