@@ -309,18 +309,17 @@ export function createWebSocketClient(opts = {}) {
309309 console . info ( '[ws] Connecting...' ) ;
310310
311311 try {
312- // NOTE: Browser WebSocket API does not support custom headers, and
313- // modern browsers no longer send an Authorization header from URL
314- // userinfo (user:pass@host) on WebSocket upgrade requests.
315- // The server's _authenticate() exclusively reads basicAuth(request)
316- // from the Authorization header, so browser clients cannot currently
317- // authenticate. Until the server is updated to accept query-param
318- // or token-based auth for WebSocket upgrades, the connection will
319- // fall through to broadcastOnly mode.
320- // TODO: Update server _authenticate() to read query.username /
321- // query.password when Authorization header is absent, then pass
322- // credentials here via searchParams.
323- const connectURL = url ;
312+ // Browser WebSocket API does not support custom headers, so we pass
313+ // credentials via query params. The server's _authenticate() reads
314+ // query.username / query.password when the Authorization header is
315+ // absent (see api-websocket-handler.js).
316+ let connectURL = url ;
317+ if ( opts . email && opts . password ) {
318+ const u = new URL ( url ) ;
319+ u . searchParams . set ( 'username' , opts . email ) ;
320+ u . searchParams . set ( 'password' , opts . password ) ;
321+ connectURL = u . toString ( ) ;
322+ }
324323
325324 socket = new WebSocket ( connectURL ) ;
326325 if ( wantsMsgpackr && msgpackrAvailable ) {
@@ -372,7 +371,6 @@ export function createWebSocketClient(opts = {}) {
372371 if ( parsed . status === 'ok' ) {
373372 authenticated = true ;
374373 console . info ( '[ws] Authenticated' ) ;
375- // Start ping timeout now — server begins sending pings after auth
376374 resetPingTimeout ( ) ;
377375 dispatch ( '_authenticated' , { } ) ;
378376 } else {
@@ -382,6 +380,19 @@ export function createWebSocketClient(opts = {}) {
382380 }
383381 return ;
384382
383+ case 'connected' :
384+ // Server sends { event: 'connected', aliasId } on successful auth,
385+ // or { event: 'connected', broadcastOnly: true } for unauthenticated.
386+ if ( parsed . aliasId && ! parsed . broadcastOnly ) {
387+ authenticated = true ;
388+ console . info ( '[ws] Authenticated (aliasId:' , parsed . aliasId , ')' ) ;
389+ resetPingTimeout ( ) ;
390+ dispatch ( '_authenticated' , { aliasId : parsed . aliasId } ) ;
391+ } else {
392+ console . info ( '[ws] Connected in broadcast-only mode' ) ;
393+ }
394+ return ;
395+
385396 default :
386397 break ;
387398 }
0 commit comments