Use the Verified User Identity
After authentication, do not trust the username or user ID provided by the browser for protected actions.
Use the identity stored in socket.data.userId.
For example, when a user sends a chat message, the backend should determine the sender from the authenticated connection.
This prevents clients from pretending to be another user by changing the username in the event payload.
Authenticated Message Handler
io.on('connection', (socket) => {
socket.on('chat:send', (payload, acknowledge) => {
const userId = socket.data.userId;
const message = payload?.message;
if (
typeof message !== 'string' ||
message.trim().length === 0 ||
message.length > 1000
) {
acknowledge?.({
success: false,
error: 'Invalid message'
});
return;
}
const chatMessage = {
senderId: userId,
message: message.trim(),
timestamp: new Date().toISOString()
};
io.emit('chat:message', chatMessage);
acknowledge?.({ success: true });
});
});The sender identity is obtained from the authenticated connection rather than from the browser payload.
Key Takeaways
Never trust a client-supplied sender identity.
Use socket.data for verified connection information.
Authorize sensitive actions on the server.