I’m a big fan of real time changes, I once created an app just using socket.io without GET, POST requests, etc…
One day I realized that I was giving too much power to socketio and I really needed to secure that. Because when I did some research, it turns out that you can hack a websocket or socketio connection, not just http requests.
I took a look at the documentation, it turns out that you can use the middleware as in express and with the same basic syntax. More about middlewares with socket.io here.
Basic SocketIO Middleware
You will find in the documentation this simple syntax that allows to create a middleware in socket.io
io.use((socket, next) => {
if (isValid(socket.request)) {
next();
} else {
next(new Error("invalid"));
}
});
That’s so simple and so powerful, it’s why love coding :)
Compatibility with Express middleware
What I like even more is the compatibility with express midlewares, this allows to use passport authentication middlewares for example and access directly to passport payload. This way, at each request or rather event of socket.io, I will have the information of the user who has emitted the event.
const app = require("express")();
const session = require("express-session");
const passport = require("passport");
const sessionMiddleware = session({ secret: "changeit", resave: false, saveUninitialized: false });
// Setting express middlewares
app.use(sessionMiddleware);
app.use(passport.initialize());
app.use(passport.session());
// convert a connect middleware to a Socket.IO middleware
const wrap = middleware => (socket, next) => middleware(socket.request, {}, next);
// Setting socket.io middlewares
io.use(wrap(sessionMiddleware));
io.use(wrap(passport.initialize()));
io.use(wrap(passport.session()));
// Socket.io middleware for checking if the user exists
io.use((socket, next) => {
if (socket.request.user) {
next();
} else {
next(new Error('Unauthorized'))
}
});
io.on('connect', (socket) => {
console.log(`new connection ${socket.id}`);
socket.on('whoami', (cb) => {
cb(socket.request.user ? socket.request.user.username : '');
});
const session = socket.request.session;
console.log(`saving sid ${socket.id} in session ${session.id}`);
session.socketId = socket.id;
session.save();
});
A complete example with Passport can be found here.
We are not safe from hackers, as developers we have to add layers of security for ourselves and our customers to ensure a minimum of security for our applications. I hope this will help you and that from now on, if you don’t do it, you will start securing your socket.io