Skip to content

feat(auth): Lock accounts after repeated failed logins#105

Merged
ebouchut merged 1 commit into
devfrom
feat/account-lockout
Jul 14, 2026
Merged

feat(auth): Lock accounts after repeated failed logins#105
ebouchut merged 1 commit into
devfrom
feat/account-lockout

Conversation

@ebouchut

@ebouchut ebouchut commented Jul 14, 2026

Copy link
Copy Markdown
Owner

This PR adds a user account lockout feature that activates after 3 failed login attempts.

  • LoginAttemptListener:
    • Counts consecutive wrong-password logins per account
    • Locks the account at the threshold: users.is_locked already maps to Spring Security accountLocked, so a locked account is rejected even with the right password.
    • A successful login resets the counter and finally stamps last_login_at.
    • Failures for unknown usernames change nothing observable (no enumeration).
  • There are two methods to unlock a locked account, both of which are audited:
    • The admin accounts page gains a locked status and an Unlock action,
    • Completing a password reset clears the lock too because it proves control of the mailbox.
  • AccountLockoutFlowTest tests the flow end-to-end with a lowered threshold:
    • Three failed login attempts lock the account,
    • The correct password is then rejected,
    • The admin unlock clears the lock and counter,
    • Then, the next login succeeds and stamps the login time.

This is part 2 of 2 in a stack made with GitButler:

LoginAttemptListener counts consecutive wrong-password logins per
account and locks the account at the threshold (5 by default,
learndev.lockout.max-attempts): users.is_locked already maps to
Spring Security accountLocked, so a locked account is rejected even
with the right password. A successful login resets the counter and
finally stamps last_login_at. Failures for unknown usernames change
nothing observable (no enumeration).

Two unlock paths, both audited: the admin accounts page gains a
Locked status and an Unlock action, and completing a password reset
clears the lock too, since it proves control of the mailbox.

AccountLockoutFlowTest drives it end to end with a lowered threshold:
three strikes lock the account, the correct password is then
rejected, the admin unlock clears lock and counter, and the next
login succeeds and stamps the login time.
@ebouchut ebouchut self-assigned this Jul 14, 2026
@ebouchut ebouchut added backend auth Authentication & authorization (login, sessions, password reset, tokens) labels Jul 14, 2026
@ebouchut ebouchut added this to the v0.9 - Code Freeze milestone Jul 14, 2026
@ebouchut ebouchut moved this to In Progress in learn-dev-project Jul 14, 2026
@ebouchut ebouchut moved this from In Progress to In Review in learn-dev-project Jul 14, 2026
Base automatically changed from feat/admin-account-management to dev July 14, 2026 17:10
@ebouchut
ebouchut merged commit a25e3e5 into dev Jul 14, 2026
1 check passed
@ebouchut
ebouchut deleted the feat/account-lockout branch July 14, 2026 17:13
@github-project-automation github-project-automation Bot moved this from In Review to Done in learn-dev-project Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auth Authentication & authorization (login, sessions, password reset, tokens) backend

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant