Files
homelable/frontend/src/hooks/useStatusPolling.ts
T
Pouzor e14a9e87aa fix: stop exposing JWT in WebSocket URL query param
Token was visible in server logs, browser history, and proxy access logs.
Backend now accepts the connection first, then validates a JSON auth
message {"token": "<jwt>"} sent by the client on open before adding
the socket to the active connections pool.
2026-03-18 00:49:03 +01:00

64 lines
1.9 KiB
TypeScript

import { useEffect, useRef } from 'react'
import { useCanvasStore } from '@/stores/canvasStore'
import { useAuthStore } from '@/stores/authStore'
interface StatusMessage {
type?: string
node_id?: string
status?: 'online' | 'offline' | 'pending' | 'unknown'
checked_at?: string
response_time_ms?: number | null
run_id?: string
devices_found?: number
}
const STANDALONE = import.meta.env.VITE_STANDALONE === 'true'
export function useStatusPolling() {
const wsRef = useRef<WebSocket | null>(null)
const { updateNode, notifyScanDeviceFound } = useCanvasStore()
const { isAuthenticated, token } = useAuthStore()
useEffect(() => {
if (STANDALONE || !isAuthenticated || !token) return
const protocol = window.location.protocol === 'https:' ? 'wss' : 'ws'
const host = window.location.host // includes port when non-standard
const url = `${protocol}://${host}/api/v1/status/ws/status`
const ws = new WebSocket(url)
wsRef.current = ws
// Send token as first message (not in URL to avoid log/history exposure)
ws.onopen = () => {
ws.send(JSON.stringify({ token }))
}
ws.onmessage = (event) => {
try {
const msg: StatusMessage = JSON.parse(event.data)
if (msg.type === 'scan_device_found') {
notifyScanDeviceFound()
} else if (msg.node_id && msg.status) {
updateNode(msg.node_id, {
status: msg.status,
response_time_ms: msg.response_time_ms ?? undefined,
last_seen: msg.status === 'online' ? msg.checked_at : undefined,
})
}
} catch {
// ignore malformed messages
}
}
ws.onerror = () => {
// silently ignore — backend may not be running in dev
}
return () => {
ws.close()
wsRef.current = null
}
}, [isAuthenticated, token, updateNode, notifyScanDeviceFound])
}