How it works
- Every login attempt (successful or failed) is recorded in a
LoginAttempttable with the identifier used (lowercased), the source IP, and the result. - If an account accumulates 5 failed attempts in the last 15
minutes, the system:
- Sets the user’s
lockedUntilfield to 15 minutes in the future. - Records an
auth.lockoutentry in the audit log withfailedAttempts,lockedUntil, and the IP of the last attempt. - Sends an email to the user notifying them of the lockout (see below).
- Sets the user’s
- During the lockout, any login attempt (even with the correct
password) responds with
403 Forbidden. - Once the 15-minute window passes, the lockout is lifted automatically on the next attempt, no manual action is required.
Notification email
When the lockout is triggered, the system sends the user an email through AWS SES with:- Subject: “Temporary lock on your woku account”.
- Body: explains that we detected several failed attempts, when the lockout is lifted, from which IP, and a CTA to reset the password.
Administrative unlock
If the user needs to log in before the window passes, an internal administrator can unlock them from the backoffice. The action is recorded asauth.unlock in the audit log with the IP of
the request.
Limitations
- Detection is per-user, not per-IP. A distributed attacker
probing many different users from multiple IPs does not trigger
the per-user lockout, but is still exposed to the global rate
limit (10 req/s, 50 req/10s, 100 req/min per IP, managed
by
@nestjs/throttler). - If the attacker uses an identifier that does not match any user, there is no lockout (there is nothing to lock), but the rate limit per IP still applies.