8fa66c9911
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
26 lines
1.1 KiB
TypeScript
26 lines
1.1 KiB
TypeScript
// Desktop-only in-memory CSRF token stash.
|
|
//
|
|
// tauri-plugin-http's fetch() runs through Rust's reqwest, which keeps its OWN
|
|
// cookie jar separate from the webview — document.cookie on tauri://localhost
|
|
// never sees the parking_csrf cookie the server sets (open upstream bug,
|
|
// tauri-apps/tauri#13045). The cookie IS still sent to the server by reqwest;
|
|
// only the client-side READ is broken. So the server echoes the same value in
|
|
// the login / me response body (sessionView's csrfToken, routes/auth.ts) and
|
|
// the desktop client keeps it here, echoing THIS in X-CSRF-Token instead of
|
|
// reading document.cookie.
|
|
//
|
|
// One module, no imports, so BOTH echo sites can share it without a cycle:
|
|
// api.ts (sets it, uses it for apiFetch mutations) and logger.ts (uses it for
|
|
// the /api/logs flush — which api.ts imports, so it can't import api.ts back).
|
|
// Never persisted: a fresh launch re-learns it via login or /api/auth/me.
|
|
|
|
let token: string | null = null;
|
|
|
|
export function setDesktopCsrfToken(value: string | null): void {
|
|
token = value;
|
|
}
|
|
|
|
export function getDesktopCsrfToken(): string | null {
|
|
return token;
|
|
}
|