security: WS auth via first-message, not query string
Tokens in URL leak through proxy access logs, browser history and
Referer headers. Now: WS opens unauthenticated, client sends
{type:'auth', token} as first message; server responds with
{type:'auth_ok'} and starts normal message processing.
5-second timeout closes any unauthenticated connection.
Frontend queues session join until auth_ok received.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+14
-7
@@ -4330,12 +4330,11 @@
|
||||
function _crWsConnect() {
|
||||
if (_crWs && (_crWs.readyState === WebSocket.OPEN || _crWs.readyState === WebSocket.CONNECTING)) return;
|
||||
const proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const token = LS.getToken() || '';
|
||||
_crWs = new WebSocket(`${proto}//${location.host}/ws?token=${encodeURIComponent(token)}`);
|
||||
_crWs = new WebSocket(`${proto}//${location.host}/ws`);
|
||||
_crWs.onopen = () => {
|
||||
_crWsReady = true;
|
||||
// Register in session so server delivers events via WS instead of SSE
|
||||
if (_sessionId) _crWs.send(JSON.stringify({ type: 'classroom_join', sessionId: _sessionId }));
|
||||
// Authenticate via first message — token never appears in URL or proxy logs
|
||||
const token = LS.getToken() || '';
|
||||
_crWs.send(JSON.stringify({ type: 'auth', token }));
|
||||
};
|
||||
_crWs.onclose = () => {
|
||||
_crWsReady = false;
|
||||
@@ -4343,9 +4342,17 @@
|
||||
if (_sessionId) setTimeout(() => { if (_sessionId) _crWsConnect(); }, 2000);
|
||||
};
|
||||
_crWs.onerror = () => { _crWsReady = false; };
|
||||
// All classroom server→client events arrive here (WS replaces SSE for classroom)
|
||||
_crWs.onmessage = e => {
|
||||
try { handleSSE(JSON.parse(e.data), true); } catch {}
|
||||
let msg;
|
||||
try { msg = JSON.parse(e.data); } catch { return; }
|
||||
if (msg.type === 'auth_ok') {
|
||||
_crWsReady = true;
|
||||
// Register in session so server delivers events via WS instead of SSE
|
||||
if (_sessionId) _crWs.send(JSON.stringify({ type: 'classroom_join', sessionId: _sessionId }));
|
||||
return;
|
||||
}
|
||||
// All other classroom server→client events
|
||||
try { handleSSE(msg, true); } catch {}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user