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

@@ -219,10 +219,21 @@ impl SupportCodeManager {
pub async fn get_by_session(&self, session_id: Uuid) -> Option<SupportCode> {
let session_to_code = self.session_to_code.read().await;
let code = session_to_code.get(&session_id)?;
let codes = self.codes.read().await;
codes.get(code).cloned()
}
/// Get the status of a code as a string (for auth checks)
pub async fn get_status(&self, code: &str) -> Option<String> {
let codes = self.codes.read().await;
codes.get(code).map(|c| match c.status {
CodeStatus::Pending => "pending".to_string(),
CodeStatus::Connected => "connected".to_string(),
CodeStatus::Completed => "completed".to_string(),
CodeStatus::Cancelled => "cancelled".to_string(),
})
}
}
impl Default for SupportCodeManager {