feat(auth): notify-and-approve gate for suspicious logins (LC-587) #555
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/LC-587-suspicious-login-approval"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
LC-587: opt-in suspicious-login notify-and-approve gate, the Lets-Chat analog of mokosh PMS-658 adapted to the pure-RP Bunyip SSO callback. When
LOGIN_APPROVAL_ENABLEDis set, a login that authenticates at the callback but looks suspicious (a new country - reusing the LC-580 geoip signal - and/or a new device) is withheld: a single-use 6-digit code is emailed and an interstitial asks the user to approve the sign-in by entering it. It notifies rather than locks (the PMS-658 decision), and is off by default because it can withhold a login.Flow
bunyip_sso::get_callbackBEFORE the session is minted (lets-chat has no password re-POST after the LC-22 pure-RP cutover). A cleared login mints the session and records its country/device as the new baseline; a suspicious one is withheld.POST /auth/bunyip/approve, which mints the session on the correct code or re-renders with an error on a wrong one.device_idcookie (SameSite=Laxso it survives the top-level OIDC redirect back to the callback), stored only as a SHA-256 hash. A login presenting nodevice_iddegrades to country-only (fail-open, no over-gating). The first-ever country/device is a silent baseline.Safety
trust_proxy_headersalready defaults true, so the real client IP is captured behind Traefik.Storage
Two SQLite tables (
login_approvals+user_login_devices), migration0041_login_approvals.sql. Notenant_id/ RLS: each deployment is single-tenant (unlike PMS-658's multi-tenant Postgres).Tests
db_login_approval.rs(new): flagged -> approved recovery, single-use replay rejection, attempt-cap burns the challenge, device baseline.login_approvalunit tests: 6-digit code shape, SHA-256 hashing, the pure new-device and suspicious-combine rules.fmt+clippy -D warningson both the standalone and saas feature sets (all targets), plus the new tests, in the pinned rust-builder.Diff note
As with LC-580, the bulk of the diff is mechanical: every test's inline
AppStateliteral gainslogin_approval_enabled: false(the repo builds full inlineAppStateliterals per test rather than sharing a helper). The substantive change is ~10 files.Deploy note
Dormant until a deployment sets
LOGIN_APPROVAL_ENABLED=1; the country signal additionally needsIP2LOCATION_DB_PATH(LC-580, provisioned in docker PR #223). README documents both.Pre-existing (not this PR)
server/tests/last_visited.rs(home_renders_welcome_when_no_cookie,home_welcome_renders_quick_actions) already fail onmain(verified by stashing this branch and running them): the i18ntfilter does not resolve the welcome copy in the test env. Untouched here; worth a separate un-red-main issue.#LC-587