Tuesday 30 June 2020

Is this authentication flow in socket.io secure?

So I have react web app that I recently decided to add sockets to (for extra functionality) and there are some cases where only authenticated users should see certain data being emitted by the server, and also some info should only be accepted by the server (via sockets) only from authenticated users, so I built the following authentication flow and I was wondering if anyone can see any security issue with it, meaning will unauthenticated users be able to see data and emit data to and from the server or is it safe enough?This is the flow:- The user login on the frontend as usual with no socket connection what so ever, and after login in they get a login token that's stored in a cookie and used for every request they make to the server to authenticate their API calls to the backend- Once a user connects to the socket, the server in the "connection" listener takes the login token from the cookie and authenticate the user- If couldn't authenticate the user then the server emits the reason to the frontend and disconnect the socket- Otherwise if managed to authenticate the user then the server adds the user to a specific room only for that user (so if the same user logs in from multiple PCs or mobile apps all their instances will be able to receive and emit data) the rooms ID structure is "room-" and then the user ID​Here's a snippet of the code: //creating socketio instance with the server's instace const io = socketio(server) //listening for new connections io.on("connection", async (socket) => { //authenticating newly connected sockets with their login token const didAuth = await authenticate(socket) //emitting the response to the client io.to(socket.id).emit("auth", didAuth) //if couldn't authenticate then disconnecting the socket if(didAuth.error) return socket.disconnect() //adding the user to their room - "userId" is added to the socket object in the authentication function once the user successfully logs in socket.join(`room-${socket.userId}`) //adding listeners for clients emits socket.on("alert-from-client", () => { //doing stuff here that only authenticated users can do }) }) //when the server needs to emit info to the clients this function is called module.exports.emitSomething = (userId, data) => { //emitting some data only authenticated users should see io.sockets.in(`room-${userId}`).emit(data) } //authenticating the socket based on the login token of the user const authenticate = async (socket) => { let didAuth = { error: true, message: "Unknown error" }; //getting the user's login token (which was generated and saved in a cookie when they logged in on the frontend) let token = getCookie(socket.request.headers.cookie, env.LOGIN_COOKIE_ID) /* ... doing authentication stuff here with the token and setting in the above "didAuth" if there was auth error and potential error message ... */ return didAuth; }

Submitted June 30, 2020 at 10:19AM by s_trader

No comments:

Post a Comment