Home > database >  Can't login using credentials stored in the database
Can't login using credentials stored in the database

Time:12-29

I created very simple site where everybody can access /about, authenticated users can access /profile and only user with "ADMIN" role can access. I added one "ADMIN" user in the DBInit.java Then I try to access /admin and I get an http basic login form. I enter adminEmail as login and admin123 as password and I can't access /admin page. So somewhere is an error in my code, and I can see it. So where is an error and how to get rid of it? If I use in memory authentication everything works well.

// In memory authentication
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
//    auth.authenticationProvider(authenticationProvider());
    
    auth.inMemoryAuthentication()
        .withUser("admin")
        .password(passwordEncoder().encode("admin"))
        .roles("ADMIN");
}

SecurityConfiguration.java

import Onlinestore.service.UserPrincipalDetailsService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
    private UserPrincipalDetailsService userPrincipalDetailsService;
    
    public SecurityConfiguration(UserPrincipalDetailsService userPrincipalDetailsService)
    {
        this.userPrincipalDetailsService = userPrincipalDetailsService;
    }
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth)
    {
        auth.authenticationProvider(authenticationProvider());
    }
    
    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
        http
                .authorizeRequests()
                .antMatchers("/about").permitAll()
                .antMatchers("/profile").authenticated()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .and()
                .httpBasic();
    }
    
    @Bean
    DaoAuthenticationProvider authenticationProvider()
    {
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        daoAuthenticationProvider.setUserDetailsService(userPrincipalDetailsService);
        
        return daoAuthenticationProvider;
    }
    
    @Bean
    public PasswordEncoder passwordEncoder()
    {
        return new BCryptPasswordEncoder();
    }
}

User.java

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;

@Entity(name = "user")
@Table(name = "users")
@NoArgsConstructor
public class User
{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Getter
    @Setter
    private int id;
    
    @Getter
    @Setter
    @Column(nullable = false)
    private String name;
    
    @Getter
    @Setter
    private String surname;
    
    @Getter
    @Setter
    @Column(nullable = false)
    private String password;
    
    @Getter
    @Setter
    @Column(name = "telephone_number", nullable = false)
    private String telephoneNumber;
    
    @Getter
    @Setter
    @Column(unique = true)
    private String email;
    
    @Getter
    @Setter
    private String country;
    
    @Getter
    @Setter
    private String address;
    
    @Getter
    @Setter
    // delimiter = ";"
    private String roleNames;
    
    public User(String name, String surname, String password, String telephoneNumber, String email, String country, String address, String roleNames)
    {
        this.name = name;
        this.surname = surname;
        this.password = password;
        this.telephoneNumber = telephoneNumber;
        this.email = email;
        this.country = country;
        this.address = address;
        this.roleNames = roleNames;
    }
}

UserPrincipal.java

import Onlinestore.entity.User;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class UserPrincipal implements UserDetails
{
    private User user;
    
    public UserPrincipal(User user)
    {
        this.user = user;
    }
    
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities()
    {
        String[] roles = user.getRoleNames().split(";");
        
        List<GrantedAuthority> authorities = new ArrayList<>();
        for (String role : roles)
        {
            authorities.add(new SimpleGrantedAuthority(role));
        }
        
        return authorities;
    }
    
    @Override
    public String getPassword()
    {
        return user.getPassword();
    }
    
    @Override
    public String getUsername()
    {
        return user.getName();
    }
    
    @Override
    public boolean isAccountNonExpired()
    {
        return false;
    }
    
    @Override
    public boolean isAccountNonLocked()
    {
        return false;
    }
    
    @Override
    public boolean isCredentialsNonExpired()
    {
        return false;
    }
    
    @Override
    public boolean isEnabled()
    {
        return false;
    }
}

UserPrincipalDetailsService.java

import Onlinestore.entity.User;
import Onlinestore.repository.UserRepository;
import Onlinestore.security.UserPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

@Service
public class UserPrincipalDetailsService implements UserDetailsService
{
    private UserRepository userRepository;
    
    public UserPrincipalDetailsService(UserRepository userRepository)
    {
        this.userRepository = userRepository;
    }
    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
    {
        User user = userRepository.findUserByEmail(username);
        return new UserPrincipal(user);
    }
}

DBInit.java

import Onlinestore.entity.User;
import Onlinestore.repository.UserRepository;
import org.springframework.boot.CommandLineRunner;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;

@Service
public class DBInit implements CommandLineRunner
{
    private UserRepository userRepository;
    private PasswordEncoder passwordEncoder;
    
    public DBInit(UserRepository userRepository, PasswordEncoder passwordEncoder)
    {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
    }
    
    @Override
    public void run(String[] args)
    {
        User user1 = new User("admin", "admin", passwordEncoder.encode("admin123"),
                " 111111111", "adminEmail", "country1", "address1", "ADMIN");

        List<User> users = Arrays.asList(user1);

        userRepository.saveAll(users);
    }
}

UserRepository

import Onlinestore.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository<User, Integer>
{
    User findUserByEmail(String email);
}

CodePudding user response:

In memory authentication expects hard coded credentials in the configuration. It does not pull credentials from the database.

If you want to use credentials from a database, the rest of your setup looks good at first glance. Try

httpSecurity
  .authorizeRequests()
    .antMatchers(PUBLIC_MATCHERS)
      .permitAll()
    .anyRequest()
      .authenticated();

Where PUBLIC_MATCHERS is an array of endpoints that do not require authentication, if you have such a thing.

CodePudding user response:

I has found an error. In class UserPrincipal I need to override this methods and return true, but not return false. I think when I return false Spring Security thinks the user is blocked, expired, disabled and so on and blocks authentication. This but there also some errors and application yet not working as I wanted to. Proper implementation of methods in UserPrincipal

@Override
public boolean isAccountNonExpired()
{
    return true;
}
    
@Override
public boolean isAccountNonLocked()
{
    return true;
}
    
@Override
public boolean isCredentialsNonExpired()
{
    return true;
}
    
@Override
public boolean isEnabled()
{
    return true;
}
  • Related