fix(desktop): WS ticket auth for the live feed; desktop logs never reached the server
The v0.1.4 Origin fix cleared only the first of two gates in /api/ws's preHandler. The second, req.jwtVerify(), reads the HttpOnly cookie — which tauri-plugin-websocket (a bare tungstenite client, no cookie jar) can never send. Every desktop handshake 401'd and use-live-feed reconnected every 10s (confirmed in the park-2 server log). - routes/ws.ts: POST /api/ws/ticket (cookie + CSRF auth) mints a 30s, single-use, in-memory ticket; the WS preHandler accepts it via an x-ws-ticket header after the Origin check, then the same report:read role check. Browser cookie path unchanged; JWT stays out of JS. - platform-ws.ts: fetch a ticket before connect, send it with the Origin header; connect failures now go through logClient (rate-limited). - logger.ts: flush read the CSRF token from document.cookie, null on desktop, so every desktop POST /api/logs 403'd and was dropped silently — no desktop client log had ever reached app_logs. Stash moved to a dependency-free lib/desktop-csrf.ts shared by api.ts and logger.ts. - backend-config.ts: ConnectScreen probe uses the unauthenticated /health (now also returns app: "parking-system") instead of accepting any 401. - README: local-AppImage release gate — tauri dev runs at http://localhost:5173, not tauri://localhost, so none of these origin-dependent bugs reproduce there. - wiki: new section + log entry; four citation corrections. Requires the server image with this commit deployed before the new desktop build connects (the ticket endpoint must exist). Claude-Session: https://claude.ai/code/session_01FWncR69HgGPuei1dLrW3cU
This commit is contained in:
+19
@@ -2841,3 +2841,22 @@ value in the login/me JSON body; the desktop client stashes it in memory and ech
|
||||
reading document.cookie. assertCsrf() itself is untouched — the cookie is still what's verified,
|
||||
and reqwest was already sending it correctly; this only fixes how the desktop client *learns* the
|
||||
value. Full detail (including the exact CSP/capability tradeoffs) on [[desktop-shell-tauri]].
|
||||
|
||||
## [2026-09-04] fix | Desktop live feed: WS handshake can't carry the cookie → single-use ticket; desktop logs never reached app_logs
|
||||
|
||||
Retrospective of the 2026-09-03/04 desktop run (six releases in 26 h) found the v0.1.4 Origin fix
|
||||
cleared only gate one of two in routes/ws.ts: gate two is req.jwtVerify() reading the HttpOnly
|
||||
cookie, and tauri-plugin-websocket has no cookie jar at all — so every desktop handshake 401'd and
|
||||
use-live-feed reconnected every 10 s (confirmed in the park-2 server log). Fixed with a 30-second,
|
||||
single-use, in-memory WS ticket minted by POST /api/ws/ticket over normal cookie+CSRF auth and
|
||||
presented in an x-ws-ticket header; Origin check still runs first, browser path unchanged, JWT
|
||||
stays out of JS. Second finding: logger.ts read the CSRF cookie via document.cookie, null on
|
||||
desktop, so every desktop POST /api/logs 403'd and was dropped silently — no desktop client log had
|
||||
EVER reached app_logs, which is why "no logs whatsoever" kept happening and why yesterday's
|
||||
logClient fix couldn't help. Stash moved to lib/desktop-csrf.ts, shared by api.ts and logger.ts;
|
||||
WS connect failures now go through logClient (rate-limited). Third: the ConnectScreen probe now
|
||||
uses the unauthenticated /health (extended with app: "parking-system") instead of accepting any
|
||||
401. Also corrected four wiki citations (WebKit 171934 scope, tauri#11518 is closed, the HTTP
|
||||
plugin does set Origin itself, the http-scope "quirk" is URLPattern default-port semantics) and
|
||||
added a local-AppImage pre-tag gate to the desktop README, since tauri dev cannot reproduce any
|
||||
of these origin-dependent bugs. Full detail on [[desktop-shell-tauri]].
|
||||
|
||||
Reference in New Issue
Block a user