I have created a custom AuthenticationProvider
to perform custom security checks. I have also created custom exceptions that inherit from AccountStatusException
to notify user status problems such as when the user has not verified his account for an specific period of time.My UserDetails
is also acustom implementation.
Here is the code for the security checks I perform. Code that is irrelevant to the case has been omitted.
public class SsoAuthenticationProvider implements AuthenticationProvider {
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = (String) authentication.getPrincipal();
User user = null;
if (username != null) {
user = getUserRepository().findByUserName(username);
if (user != null) {
if (user.getEnabled() != 0) {
if ((user.getUserDetail().getConfirmed() != 0)
|| ((new Date().getTime() - user.getUserDetail().getRequestDate().getTime()) / (1000 * 60 * 60 * 24)) <= getUnconfirmedDays()) {
if (getPasswordEncoder().isPasswordValid(user.getPassword(),
(String) authentication.getCredentials(), user)) {
user.authenticated = true;
user.getAuthorities();
}
} else {
throw new UserNotConfirmedAndTimeExceeded(
"User has not been cofirmed in the established time period");
}
} else {
throw new DisabledException("User is disabled");
}
} else {
throw new BadCredentialsException("User or password incorrect");
}
} else {
throw new AuthenticationCredentialsNotFoundException("No credentials found in context");
}
return user;
}
}
The SsoAuthenticationProvider
checks:
- That the username is registered (exists in the db)
- That the user has confirmed his email
- If the user has not confirmed his email, check that he is still in the grace period (this is a few days we give users to confirm their email while letting them access the site)
- If the user has not confirmed email and he is not in the grace period, throw security exception to signal these status and reject authentication
The problem is that not all of these exceptions are thrown up the stack up to the controller so it seems impossible to inform the user about the login problem.
Using UserDetails
methods such as isEnabled()
(and similar) is not a possibility as the semantics of our different user account statuses are completely different.
Is this the right approach to build custom security with custom exceptions? Should i implement sth else to make this work?