I am implementing spring security in my application and I want to prevent brute force password attempts for a particular user account. Whenever a user tries to login with invalid credentials, I am throwing an AuthException() with a basic Invalid Username Or Password message and in addition to I now want to increase a counter in my database for password_attempt to handle brute force attack.
I tried implementing a case where I run a separate transaction using Propagation.REQUIRES_NEW but when throwing exception from outer transaction, inner transaction is also rolled back. How to prevent this?
Also I read it somewhere when searching about it to use spring application events to handle this implementation. But will it be a bad design? Because from UserAuthenticationService I will publish an event, the event will again @Autowired UserAuthenticationService and call the function to increase the counter in the database. Or is there a way to call the spring event automatically whenever I throw AuthException Or BadCredentialException so that I dont have to publish it explicitly?
PS: I have added @Transactional on class level (UserAuthenticationService.class) snd both methods are in the same class
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updatePasswordAttempt(Long userId, Integer attemptCount){
userRepository.updatePasswordAttempt(userId, attemptCount);
}
public void validatePassword(String password, UserEntity user){
if(Boolean.TRUE.equals(matchPassword(password, user.getPassword()))){
if(user.getPasswordAttempt().equals(0)) return;
updatePasswordAttempt(user.getId(), 0);
return;
}
int attemptCount = user.getPasswordAttempt() + 1;
updatePasswordAttempt(user.getId(), attemptCount);
throw new AuthException(INVALID_PASSWORD.getMessage(), INVALID_PASSWORD.getCode());
}