diff options
| author | Agando <roduccomm@gmail.com> | 2026-11-02 21:51:31 +0100 |
|---|---|---|
| committer | Agando <roduccomm@gmail.com> | 2026-11-02 21:51:31 +0100 |
| commit | 46a1b29d1e60fa0ac478fdff45dc6456807d6297 (patch) | |
| tree | c91216d57bf2ad247a3e427fb532d8815681bed5 /modules/core/module-agent-registry.js | |
| parent | 4587c757b17d8a92df7c98ec37ace4c5500a4f5a (diff) | |
fix(auth): one session writer for every login path; expire dead credentials
Third occurrence of the same class of bug, and the first fix is why: commit e95b7be
(2026-11-01, "multi-session .newsession v3") touched exactly ONE hunk of
auth-file-api.py — handle_login. handle_device_poll, handle_telegram_login and
handle_register kept overwriting the whole .newsession with a single-session v2
payload, so a phone sign-in logged the desktop out and the loser held a session id
no store knew: permanent `401 Invalid session or API key` (newOS4 asked for a login
it could never complete). Measured: agando's store held 1 entry (sha8 45cb7819) while
the phone sent 9ac607f1 for 3 h; 26 device-polls in 2 s from one page minted 26
cookies and only the last write survived, which also drained the shared nginx
`webx11` zone (11x 503 on /admin/api/*).
api/webx11_auth.py
- add_session() is now THE writer: v3 `sessions[]` (cap 5) under a per-user
`flock` (LOCK_DIR outside the spaces), plus the legacy `.session` mirror
- module-level import so no handler has to reach for it lazily
api/auth-file-api.py
- device-poll / telegram-login / register / recover-by-backup-code all call
add_session(); a bare write_newsession_file() is now only the admin-gated
handle_create_session
- handle_device_poll runs its approved branch under a per-code `flock` and mints
exactly one session per approved code (idempotent under a poll storm), with a
cheap pre-lock reject so unvalidated codes cannot mint lock files
- handle_me_cookie expires an unknown session cookie (Set-Cookie Max-Age=0,
code SESSION_DEAD): the cookie is HttpOnly, so no page could ever clear a dead
credential and every load re-sent it
api/newcrypto.py
- write_newsession_file() is atomic (tmp + fsync + os.replace); the temp name
carries pid+tid because a fixed `<file>.tmp` lets two concurrent writers of one
store steal each other's temp file (reproduced: FileNotFoundError)
admin-login.html single-flight poll (polling/finished guards) — 26 calls -> 1
dashboard.html device-code fallback when the Telegram popup has no opener
spaces/newos4/* 401 -> session-repair notice + endpoint normalisation, v4.6.144
nginx /api/auth/ + /api/security/ on zone wx11auth (120r/m, burst 60)
admin/scripts/verify-session-writers.py NEW static guard, wired into smoke-auth.sh
Proof (live, after restart): 5 concurrent polls on one approved code -> 5x approved,
1 distinct session id, store v3 with 2 entries, pre-fix session still valid; dead
cookie -> 401 + Set-Cookie expiry, valid cookie -> 200; 200-call auth burst -> 503s
only on /api/auth/, /admin/ stayed 302; smoke-auth.sh PASS. Guard RED (3 offenders)
-> GREEN. Backups: /home/darkbot/backups/authfix-20261102_214424
Diffstat (limited to 'modules/core/module-agent-registry.js')
0 files changed, 0 insertions, 0 deletions