Issue
Vaadin has a springboot-security-integration via "LoginForm" by setting LoginForm.action("login")
which sends the form forward to springboot.
I see the user in my database and I see hibernate making a sql query when trying to login, but the login doesn't work nor does it show me any error or exception to handle.
What I do:
- Register a user via
registerUser in UserService.class
- See Hibernate interacting with postgres via following output in the console:
Hibernate: select user0_.id as id1_0_, user0_.app_user_role as app_user2_0_, user0_.email as email3_0_, user0_.enabled as enabled4_0_, user0_.locked as locked5_0_, user0_.password as password6_0_, user0_.username as username7_0_ from public.user user0_ where user0_.username=?
Hibernate: insert into public.user (app_user_role, email, enabled, locked, password, username) values (?, ?, ?, ?, ?, ?)
- switch to the Login-View
- put in the same credentials I just used to register
- See Hibernate interacting with postgres via following output in the console:
Hibernate: select user0_.id as id1_0_, user0_.app_user_role as app_user2_0_, user0_.email as email3_0_, user0_.enabled as enabled4_0_, user0_.locked as locked5_0_, user0_.password as password6_0_, user0_.username as username7_0_ from public.user user0_ where user0_.username=?
- Get redirected to
localhost:8080/login?error
Checking via psql I can see that the user is saved in the database with an encrypted password, but I still can't log in using that account. There must be something I am missing - any help would be very appreciated as I've been reading through several documentations now, everyone suggesting something else.
WebSecurityConfig.class
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends VaadinWebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
setLoginView(http, Login.class);
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/images/**");
super.configure(web);
}
}
Login.class (View (Vaadin))
@Route(value = "login")
@AnonymousAllowed
public class Login extends VerticalLayout implements BeforeEnterObserver {
LoginForm loginForm;
public Login() {
loginForm = new LoginForm();
loginForm.setId("login-form");
loginForm.setAction("login");
add(loginForm);
setAlignItems(Alignment.CENTER);
setJustifyContentMode(JustifyContentMode.CENTER);
setSizeFull();
}
@Override
public void beforeEnter(BeforeEnterEvent beforeEnterEvent) {
// inform the user about an authentication error
if(beforeEnterEvent.getLocation()
.getQueryParameters()
.getParameters()
.containsKey("error")) {
loginForm.setError(true);
}
}
}
UserService.class
@Service
public class UserService implements UserDetailsService {
private final UserRepository userRepository;
@Lazy
private final PasswordEncoder passwordEncoder;
private final static String USER_NOT_FOUND = "User with name %s does not exist!";
@Autowired
public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
public void registerUser(User user) throws UsernameAlreadyExistsException {
try {
loadUserByUsername(user.getUsername());
throw new UsernameAlreadyExistsException();
} catch(UsernameNotFoundException e) {
user.setPassword(passwordEncoder.encode(user.getPassword()));
userRepository.save(user);
}
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println(username);
return userRepository.findByUsername(username).orElseThrow(() -> {
System.out.println("Username not found " + username);
return new UsernameNotFoundException(String.format(USER_NOT_FOUND, username));
});
}
}
Edit/Solution:
Well not even 10 minutes after posting here I have found the answer, despite having struggled with this for almost a whole day now.
When implementing UserDetails in my User.class, the implemented methods isAccountNonExpired()
and isCredentialsNonExpired()
by default implementation return false
. Which ... well, causes the account to be expired. Therefore you can't log in. Sadly I could only see that error-message when finally found the property I need to set for security-debugging.
logging.level.org.springframework.security=DEBUG
Solution
Well not even 10 minutes after posting here I have found the answer, despite having struggled with this for almost a whole day now.
When implementing UserDetails in my User.class, the implemented methods isAccountNonExpired()
and isCredentialsNonExpired()
by default implementation return false. Which ... well, causes the account to be expired. Therefore you can't log in. Sadly I could only see that error-message when finally found the property I need to set for security-debugging.
logging.level.org.springframework.security=DEBUG
Answered By - slothinflippycar
Answer Checked By - Mary Flores (JavaFixing Volunteer)