Enhance socket authentication with access and refresh token handling

This commit is contained in:
2025-08-29 17:42:55 +05:30
parent c473c5b7a0
commit 37c92c13c3

View File

@@ -1,6 +1,7 @@
import { Server, Socket } from "socket.io";
import jwt from "jsonwebtoken";
import { eventHandlerMap } from "../events/eventHandaler";
import { existingUserData } from "../../shared/services/AuthService";
interface UserPayload {
userId: string;
@@ -16,7 +17,7 @@ interface UserSocketInfo {
const connectedUsersByOrg: { [organization: string]: UserSocketInfo[] } = {};
export const SocketServer = (io: Server) => {
export const SocketServer = async (io: Server) => {
// ✅ Declare all namespaces here
const namespaceNames = ["/edge", "/project", "/graph"];
@@ -26,55 +27,91 @@ export const SocketServer = (io: Server) => {
// ✅ Attach common handler to each namespace
namespaceNames.forEach((nspName) => {
const namespace = io.of(nspName);
namespace.use(async (socket: Socket, next) => {
try {
const accessToken = socket.handshake.auth.accessToken as string;
const refreshToken = socket.handshake.auth.refreshToken as string;
if (!accessToken) return next(new Error("No access token provided"));
const jwt_secret = process.env.JWT_SECRET as string;
try {
const decoded = jwt.verify(accessToken, jwt_secret) as UserPayload;
// namespace.use((socket: Socket, next) => {
// try {
// socket.handshake.auth
// console.log('socket.handshake.auth: ', socket.handshake.auth);
// const token = socket.handshake.auth.token as string;
// if (!token) return next(new Error("No token provided"));
const mailExistance = await existingUserData(decoded.email, decoded.organization);
if (!mailExistance) {
return next(new Error("Unauthorized user - not in system"));
}
// const jwt_secret = process.env.JWT_SECRET as string;
// const decoded = jwt.verify(token, jwt_secret) as UserPayload;
(socket as any).user = decoded;
return next();
// (socket as any).user = decoded;
// next();
// } catch (err) {
// next(new Error("Authentication failed"));
// }
// });
} catch (err: any) {
if (err.name === "TokenExpiredError") {
if (!refreshToken) {
return next(new Error("Token expired and no refresh token provided"));
}
try {
const refreshSecret = process.env.REFRESH_JWT_SECRET as string;
const decodedRefresh = jwt.verify(refreshToken, refreshSecret) as UserPayload;
const mailExistance = await existingUserData(decodedRefresh.email, decodedRefresh.organization);
if (!mailExistance) {
return next(new Error("Unauthorized user - not in system"));
}
// Generate new access token
const newAccessToken = jwt.sign(
{ email: decodedRefresh.email, organization: decodedRefresh.organization },
jwt_secret,
{ expiresIn: "3h" } // adjust expiry
);
socket.emit("newAccessToken", newAccessToken);
(socket as any).user = decodedRefresh;
return next();
} catch (refreshErr) {
return next(new Error("Refresh token expired or invalid"));
}
}
return next(new Error("Invalid token"));
}
} catch (err) {
return next(new Error("Authentication error"));
}
});
namespace.on("connection", (socket: Socket) => {
console.log(`✅ Connected to namespace ${nspName}: ${socket.id}`);
// const user = (socket as any).user as UserPayload;
// const { organization, userId } = user;
const user = (socket as any).user as UserPayload;
const { organization, userId } = user;
// if (!onlineUsers[organization]) onlineUsers[organization] = new Set();
// onlineUsers[organization].add(socket.id);
if (!onlineUsers[organization]) onlineUsers[organization] = new Set();
onlineUsers[organization].add(socket.id);
// if (!connectedUsersByOrg[organization]) connectedUsersByOrg[organization] = [];
// connectedUsersByOrg[organization].push({ socketId: socket.id, userId, organization });
if (!connectedUsersByOrg[organization]) connectedUsersByOrg[organization] = [];
connectedUsersByOrg[organization].push({ socketId: socket.id, userId, organization });
console.log(`✅ Connected to namespace ${nspName}: ${socket.id}`);
// 🎯 Common event handler
// Common event handler
socket.onAny((event: string, data: any, callback: any) => {
const handler = eventHandlerMap[event];
if (handler) {
handler(event, socket, io, data, connectedUsersByOrg, callback);
} else {
console.warn(`⚠️ No handler found for event: ${event}`);
console.warn(` No handler found for event: ${event}`);
}
});
// socket.on("disconnect", () => {
// onlineUsers[organization]?.delete(socket.id);
// if (onlineUsers[organization]?.size === 0) {
// delete onlineUsers[organization];
// }
// connectedUsersByOrg[organization] = connectedUsersByOrg[organization]?.filter(
// (u) => u.socketId !== socket.id
// );
// });
socket.on("disconnect", () => {
onlineUsers[organization]?.delete(socket.id);
if (onlineUsers[organization]?.size === 0) {
delete onlineUsers[organization];
}
connectedUsersByOrg[organization] = connectedUsersByOrg[organization]?.filter(
(u) => u.socketId !== socket.id
);
});
});
});