Security: Require authentication for all WebSocket and API endpoints

- REST API: All session/code/machine endpoints now require AuthenticatedUser
- Viewer WebSocket: Requires JWT token in query params (token=...)
- Agent WebSocket: Requires either valid support code OR API key
- Dashboard: Passes JWT token when connecting to viewer WS
- Native viewer: Passes token in protocol URL and WebSocket connection
- Added AGENT_API_KEY env var support for persistent agents
- Added get_status() to SupportCodeManager for auth validation

This fixes the security vulnerability where unauthenticated agents
could connect and appear in the dashboard without any credentials.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-30 06:30:28 -07:00
parent 56a9496f98
commit 4614df04fb
6 changed files with 136 additions and 17 deletions

View File

@@ -971,7 +971,8 @@
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
const serverUrl = encodeURIComponent(protocol + "//" + window.location.host + "/ws/viewer");
const protocolUrl = `guruconnect://view/${connectSessionId}?server=${serverUrl}`;
const token = localStorage.getItem("authToken");
const protocolUrl = `guruconnect://view/${connectSessionId}?server=${serverUrl}&token=${encodeURIComponent(token)}`;
// Try to launch the protocol handler
// We use a hidden iframe to avoid navigation issues
@@ -1109,7 +1110,8 @@
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
const viewerName = user?.name || user?.email || "Technician";
const wsUrl = `${protocol}//${window.location.host}/ws/viewer?session_id=${sessionId}&viewer_name=${encodeURIComponent(viewerName)}`;
const token = localStorage.getItem("authToken");
const wsUrl = `${protocol}//${window.location.host}/ws/viewer?session_id=${sessionId}&viewer_name=${encodeURIComponent(viewerName)}&token=${encodeURIComponent(token)}`;
console.log("Connecting chat to:", wsUrl);
chatSocket = new WebSocket(wsUrl);