Session-based Authorization in socket.io

socket.io authorization

Finding a decent article about session based authorization in socket.io is more difficult than one expected. To be honest, socket.io wiki page on authorization was quite simple to follow and understand, but when it came to session based authorization, I got lost. This post will show how you can take advantage of Express session middleware and socket.io authorization middleware to create a very simple authorization mechanism when establishing new socket.io connections.

Before reading this post, I strongly suggest you get familiar with Express and Socket.IO. I kept things as simple and minimal as possible, so you really don’t need more than a couple of hours to learn what needs to be learned if you’re a complete newbie.

Disclaimer: the original concept was published in Daniel Baulig’s blog. I mainly adapted it to work with Express 3.x.x.

Global Authorization vs Namespace Authorization

First I would like to distinguish between two authorization scopes that are currently supported by socket.io, namely – Global and Namespace. Global authorization will be used to authorize any attempt to open a (socket.io) connection against our Node application. Namespace authorization, on the other hand, allows you to use different authorization rules when accepting connections to a specific socket.io namespace (more on namespaces can be found here)

In this post I will exemplify only how to enable Global authorization, although from the looks of things, namespace authorization is quite straightforward once you understand global authorization.

A Few Words about Timing

It’s important to understand that the authorization process takes place during handshake. This means that, prior to authorization, no socket connection is established. As a matter of fact, because the handshakes in socket.io are implemented as HTTP calls, one can use the HTTP context to get relevant information on the user who’s trying to connect. As you’ll see next, I will be using cookie data to authorize any user that tried to establish a socket connection to the server.

Session-based Authorization

As I said, I will be using cookie data to authorize our John Dow. Specifically, I will be using the user’s session id to make sure that indeed this user went through the system. The trick here is to use Express’ session middleware to assign a signed session id to the user, so the next time he sends a request (in our case that would be during socket.io handshake) it will be possible to ascertain that this user is a valid user and not a scoundrel. Theoretically, I could also fetch more information about the user using his session id, but I felt that it’s out of scope for this article. I admit that this kind of authorization method is naive, but it’s good enough to get you started.

Time to Code!

I believe I said more than enough on the subject at hand, and now would be the right time to start looking at code. The complete source code takes less then 70 lines (including elaborate comments) and should be enough for anyone with some experience with Express and Socket.IO. Nonetheless I will guide you through the code so there are no complaints.

Client side: index.html

We begin by creating an HTML file called (surprisingly) index.html:

As you can see, our client side is nothing more then several lines of javascript establishing a socket.io connection with our local server. Once connection is established, you will be able to see time slipping away between your fingertips (millisecond ticks) inside your browser console.

Notice that I’m also listening to the error event, in case the connection cannot be established, or access is denied by the authorization process.

Configuring Express

Now let’s create and configure Express:

Pay special notice to the the fact that we’re using the session middleware that ships with Express to support sessions. This middleware is responsible for generating session ids for new users when they first login to the system.

The session middleware uses a secret value to sign the session id. We will use this mechanism to our advantage when we try to authorize an incoming socket.io connection.

The lines following the Express configuration code are responsible for serving our precious index.html when a user connects to the server.

The last two lines construct an HTTP server over the Express application, and binding it port 3000. Feel free to run node server.js and open your browser at http://localhost:3000. You should be seeing a single line saying: Open the browser console to see tick-tocks!

Configuring Socket.IO

Next we need to configure socket.io:

Now we’re getting to the tricky part. First we need to bind socket.io to our HTTP server. That would be the first line of code – piece of cake.

The next block is the reason we’re all here – by calling io.set('authorization', function (handshakeData, accept) we instruct socket.io to run our authorization code when performing a handshake.

The logic goes as follows: first we check if there’s a cookie associated with the handshake request. In case the user already logged into our system there should be a cookie containing his session id. If no cookie is found the user is rejected.

If a cookie is found, we try to parse it. The crucial line here is connect.utils.parseSignedCookie(handshakeData.cookie['express.sid'], 'secret'), which tries to unsign the session id cookie value using the same secret key used for signing. If the cookie was indeed signed by our server than the reverse operation should give us the real session id. This is actually our way of making sure that the user trying to connect is someone we “know” and not some fake user trying to hack into our system. Notice that in case we did not succeed in unsigning the value, the return value should equal to the original value, indicating a problem.

The next couple of lines in the full source code are standard socket.io and I won’t go into details explaining them.

That’s it! You’re ready to implement whatever authorization algorithm you want. Enjoy socket.io!

Shahar Kedar

With over 10 years of experience, I’ve been doing everything from hands on programming to complete system architecture. As infrastructure team leader at BigPanda (and before that at Thomson Reuters) I’m responsible for designing and building the IT and software infrastructure that make products tick. My passions in life (in this order): my wife and son, gourmet, cinema and code as craft.

Twitter LinkedIn 

5 thoughts on “Session-based Authorization in socket.io

  1. Thank you for the attribution.

  2. Thank you very much for the excellent tutorial and explanations. I am very new to this, however, and have some very fundamental questions:

    I am making a web app with Node.js, socket.io, and express, in which users log in to accounts. I simply want to implement a “keep me logged in” option. How would I supplement your example to do this (assume I already have a working database and everything necessary to log a user in)?
    In the io.on(‘connection’) block, do I simply add a ‘username’ argument to the header cookie, and update that upon successful login (socket.handshake.headers.cookie.username = ‘xxxx’)? Or, do I add such an argument to the handshakeData (not the header cookie)?
    Or, is there a way to associate a user with their express.sid? How do I ensure it is secure?
    Do I need to do anything to ensure the cookie is signed after modification (i.e., will need to be parsed in the future)?

    Again, I am fairly new to this material, so if some of my questions are entirely wrong ways to implement something, please let me know.
    Thank you very much. Any help would be very much appreciated.

    • Hi Danny,

      There are probably serverl ways of implementing persistent login, but there are two I could think of in this context. The first way, as you suggested, is to use a login cookie and then pass any login information to the web-socket connection context using the handshakeData argument. Notice though, that this data will have to be extracted, verified and set on the handshakeData argument during the authorization stage (i.e. inside the io.set('authorization', function (handshakeData, accept) {..} block), and not when handling the ws ‘connection’ event (i.e. inside the io.on('connection', function (socket) {..} block). When handling the ‘connection’ event, any handshake data will be accessible through the socket.handshake property. Regarding security, just make sure that you follow some standard guidelines as to what should be putting in the login cookie. Note that all cookies are signed so the actual data inside the login cookie should be fairly safe.

      Another way of “remembering” users is to tie their express sid to their login information internally on the server side. You could use session MemoryStore or Redis to accomplish that. In this case only the session id is passed between clients and your server, and any sensitive information is stored only on your servers. Consult this post if you want to implement persistent login this way.

      Also, consider using the excellent Passport library for doing authentication in Node.js.

      Hope this helps!

  3. How does the code verify that the session actually exists? Wouldn’t we need to query the session store for the sid?

    As an example: a user chose to logout and the session gets closed on the server. The server would still accept the WebSocket session?

    • You’re probably right. The purpose of this post was not to cover all the edge cases of session management, but rather providing a starting point for implementing authorization over WebSockets.

Leave a Reply

Your email address will not be published. Required fields are marked *


8 − four =

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>