A simple solution to a simple problem. I expected a concise answer to already be out there but I could not find it; so I wrote it. If you are interested in the details surrounding this solution, read on after the code snippets.
Locking a user’s account after a certain amount of incorrect password attempts is a common requirement for an application. To my surprise —because Spring is what I consider to be magic — Spring Security does not possess out-of-the-box functionality to achieve this. There is, however (of course), a mechanism for developers to implement such behavior.
Oddly my Google searches did not turn up any surefire solutions. The answers I found were all spurious; either being outdated or behaving incorrectly.
Worked perfectly for the error scenario. The success scenario was where we realized that an ApplicationListener type solution was not viable.
The Event above would not fire at all, and AuthenticationSuccessEvent would fire even when the password was incorrect. So, AuthenticationFailureBadCredentialsEvent would fire, followed by AuthenticationSuccessEvent which is obviously incorrect. Perhaps I do not understand how these events truly behave but regardless, their respective names are rather misleading.
setPostAuthenticationChecks: runs only after a user has supplied valid credentials.
setPreAuthenticationChecks: runs before the supplied credentials are validated. NOTE: this checker is executed after loadUserByUsername which means that the username value present on the UserDetails argument will be valid — assuming you throw an exception in loadUserByUsername if the username is incorrect —so you just need to validate the password at this point.
The two methods above are the fundamental strategies required. The password logic you implement in the overridden check does not have to be identical to ours. For those of you interested in our implementation:
Please feel free to ask any questions. I am always open to suggestions pertaining to the improvement of my writing
Thanks for reading