It should be in a Service Layer.
public interface UserService {
public User findByLogin(final String userName);
}
And in a Service implementation :
public class UserServiceImpl implements UserService {
@Inject
private UserRepository userRepository;
public User findByLogin(final String userName, final String password) {
Preconditions.checkArgument(!Strings.isNullOrEmpty(userName), "Username is mandatory !");
return Preconditions.checkNotNull(userRepository.findByLogin(userName), "User not found !");
}
}
And an Identity provider service :
public class InternalIdentityProviderImpl implements ... {
@Inject
private UserService userService;
public void authenticate(final String login, final String password) throws BadCredentialsException, IdentityNotFoundException {
try {
Preconditions.checkArgument(!Strings.isNullOrEmpty(login), "Username is mandatory !");
Preconditions.checkArgument(!Strings.isNullOrEmpty(password), "Username is mandatory !");
catch(Exception e) {
throw new BadCredentialsException(e);
}
// Check user
try {
User internal = Preconditions.checkNotNull(userService.findByLogin(username));
} catch(Exception e) {
// logs
throw new IdentityNotFoundException(e);
}
// Shiro authentication
Subject user = SecurityUtils.getSubject();
user.login(new UsernamePasswordToken(username, password));
}
}
You should decorelate how the user is retrieved from the identity provider, and how it is validated by your identification system.
Currently I used RuntimeException thrown by Guava Preconditions, but you can use a specific handcrafted Exception.
ie:
- IdentityNotFoundException : from your identity provider.
- BadCredentialsException : from your identification system.
This service could be called from the controller, and handle the exception to display the right message.