mirror of
https://github.com/screentinker/screentinker.git
synced 2026-08-13 22:03:13 -06:00
The only throttle on POST /api/auth/login was the per-IP limiter in server.js. That bounds one noisy source and nothing else: it does not bound a distributed attempt, and it is only as accurate as a deployment's proxy configuration. Nothing counted failures against the account actually being attacked, and nothing cleared such a count on success because no such count existed. lib/login-lockout.js mirrors lib/totp-lockout.js and lib/pair-lockout.js so there is one lockout idiom here rather than three. 10 failed passwords lock an account for 15 minutes. Keyed on user.id, never on the submitted email: the email is attacker-supplied and unbounded, so keying on it would let anyone grow the Map without limit — the same class of bug fixed elsewhere in this campaign. A user id only exists for a real account, so the key space is bounded by the user table and needs no eviction sweep, exactly like totp-lockout. A locked account returns the SAME 401 and body as a wrong password. A distinct 429 would tell an attacker "this account exists and is under attack", turning login into an account-existence oracle; the test asserts the locked response is byte-identical to both the wrong-password and unknown-account responses. The trade is that a locked-out legitimate user sees the generic message, so the trip is recorded in activity_log (auth:login_locked) for the operator instead. The counter is cleared as soon as the password verifies — before the TOTP and email-verification branches, which return early and never reach issueSession, so a reset placed there would never fire for those accounts. SSO paths do not share this code and are unaffected. Frontend needs no change: login.js renders any non-ok body's `error` string verbatim, and the body is unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| config | ||
| db | ||
| lib | ||
| middleware | ||
| player | ||
| routes | ||
| scripts | ||
| services | ||
| test | ||
| ws | ||
| .gitignore | ||
| config.js | ||
| package-lock.json | ||
| package.json | ||
| server.js | ||
| version.js | ||