From 7a75b9d2673599c60cf900ac9d344bfdedf9e5dc Mon Sep 17 00:00:00 2001 From: Rohit Date: Sun, 30 Mar 2025 00:20:12 +0530 Subject: [PATCH] feat: get user id from namespace auth --- server/src/socket-connection/connection.ts | 105 ++++++++++++++------- 1 file changed, 71 insertions(+), 34 deletions(-) diff --git a/server/src/socket-connection/connection.ts b/server/src/socket-connection/connection.ts index 9fad861b..66294ecf 100644 --- a/server/src/socket-connection/connection.ts +++ b/server/src/socket-connection/connection.ts @@ -1,6 +1,6 @@ import { Namespace, Socket } from 'socket.io'; import { IncomingMessage } from 'http'; -import { verify, JwtPayload } from 'jsonwebtoken'; +import { verify, JwtPayload, sign } from 'jsonwebtoken'; import logger from "../logger"; import registerInputHandlers from '../browser-management/inputHandlers'; @@ -12,48 +12,85 @@ interface AuthenticatedSocket extends Socket { request: AuthenticatedIncomingMessage; } +declare global { + var userContextMap: Map; +} + +if (!global.userContextMap) { + global.userContextMap = new Map(); +} + +/** + * Register browser-user association in the global context map + */ +export function registerBrowserUserContext(browserId: string, userId: string) { + if (!global.userContextMap) { + global.userContextMap = new Map(); + } + global.userContextMap.set(browserId, userId); + logger.log('debug', `Registered browser-user association: ${browserId} -> ${userId}`); +} + /** * Socket.io middleware for authentication * This is a socket.io specific auth handler that doesn't rely on Express middleware */ const socketAuthMiddleware = (socket: Socket, next: (err?: Error) => void) => { - const cookies = socket.handshake.headers.cookie; - if (!cookies) { - return next(new Error('Authentication required')); + // Extract browserId from namespace + const namespace = socket.nsp.name; + const browserId = namespace.slice(1); + + // Check if this browser is in our context map + if (global.userContextMap && global.userContextMap.has(browserId)) { + const userId = global.userContextMap.get(browserId); + logger.log('debug', `Found browser in context map: ${browserId} -> ${userId}`); + + const authSocket = socket as AuthenticatedSocket; + authSocket.request.user = { id: userId }; + return next(); + } + + const cookies = socket.handshake.headers.cookie; + if (!cookies) { + logger.log('debug', `No cookies found in socket handshake for ${browserId}`); + return next(new Error('Authentication required')); + } + + const tokenMatch = cookies.split(';').find(c => c.trim().startsWith('token=')); + if (!tokenMatch) { + logger.log('debug', `No token cookie found in socket handshake for ${browserId}`); + return next(new Error('Authentication required')); + } + + const token = tokenMatch.split('=')[1]; + if (!token) { + logger.log('debug', `Empty token value in cookie for ${browserId}`); + return next(new Error('Authentication required')); + } + + const secret = process.env.JWT_SECRET; + if (!secret) { + logger.error('JWT_SECRET environment variable is not defined'); + return next(new Error('Server configuration error')); + } + + verify(token, secret, (err: any, user: any) => { + if (err) { + logger.log('warn', `JWT verification error: ${err.message}`); + return next(new Error('Authentication failed')); } - const tokenMatch = cookies.split(';').find(c => c.trim().startsWith('token=')); - if (!tokenMatch) { - return next(new Error('Authentication required')); + // Normalize payload key + if (user.userId && !user.id) { + user.id = user.userId; + delete user.userId; } - const token = tokenMatch.split('=')[1]; - if (!token) { - return next(new Error('Authentication required')); - } - - const secret = process.env.JWT_SECRET; - if (!secret) { - return next(new Error('Server configuration error')); - } - - verify(token, secret, (err: any, user: any) => { - if (err) { - logger.log('warn', 'JWT verification error:', err); - return next(new Error('Authentication failed')); - } - - // Normalize payload key - if (user.userId && !user.id) { - user.id = user.userId; - delete user.userId; // temporary: del the old key for clarity - } - - // Attach user to socket request - const authSocket = socket as AuthenticatedSocket; - authSocket.request.user = user; - next(); - }); + // Attach user to socket request + const authSocket = socket as AuthenticatedSocket; + authSocket.request.user = user; + next(); + }); }; /**