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());
}