Phase 19: Local Auth (No-OIDC Mode) #23

Merged
luckberg merged 78 commits from gsd/phase-19-local-auth-no-oidc-mode into main 2026-06-18 06:25:00 -04:00
Showing only changes of commit c437f408bb - Show all commits
+10 -1
View File
@@ -87,12 +87,21 @@ localAuthRouter.post('/local/login', zValidator('json', loginSchema, noEchoHook)
const attempt = loginAttempts.get(ip);
// 423: account locked (>= LOCKOUT_FAILURES total failures, admin must reset)
// Check lockedOut FIRST — lockout takes precedence over rate window.
if (attempt?.lockedOut) {
return c.json({ error: 'Account locked' }, 423);
}
// 429: rate window — >= RATE_WINDOW_FAILURES failures within the cooldown window
// 429: rate window — >= RATE_WINDOW_FAILURES failures within the cooldown window.
// Increment the counter even on 429 so continued brute-force accumulates toward lockout.
if (attempt && attempt.count >= RATE_WINDOW_FAILURES && Date.now() < attempt.lockedUntil) {
attempt.count += 1;
attempt.lockedUntil = Date.now() + RATE_WINDOW_SECS * 1000;
attempt.lockedOut = attempt.count >= LOCKOUT_FAILURES;
loginAttempts.set(ip, attempt);
if (attempt.lockedOut) {
return c.json({ error: 'Account locked' }, 423);
}
return c.json({ error: 'Too many attempts' }, 429);
}