Add Authentication to Sockets

Learn how to add authentication to sockets.

We can use Socket authentication when we want to restrict a client’s access to a real-time connection. This is useful when we don’t wish specific clients to access our application. For example, we would add an authentication code to a Socket when a user login is required to access the application. The default Socket does not know that our application requires a login. When we add authentication checks at the very edge of our application in the Socket, we’re able to avoid writing code that checks if there is a logged-in user lower in the system. This improves our system’s maintainability because our user session check exists in a single location.

Phoenix calls a Socket module’s connect/3 callback when a new client connects. We add our authentication code and either accept or reject access to the connection. A Socket’s connect/3 callback function returns the tuple {:ok, socket} when the connection is allowed, or :error when the connection is rejected.

The connect/3 callback is also used to store data for the life of the connection. We can store any data we want in the Socket.assigns state. In our example of user login, we would store the authenticated user’s ID. This lets us know which user the connection is for in our Channel code without reauthenticating the user. The Channel authorization examples in the next section will use the Socket state.

We can add Socket authentication to our application using a secured signed token.

Securing a Socket with signed tokens

WebSockets lack CORSCross-Origin Resource Sharing restrictions used by other types of web requests. This exposes the most significant vulnerability is a CSRFCross-Site Request Forgery attack. In a CSRF attack, a different website controlled by the attacker initiates a request to our application. The attacker may use this connection as if they were the user, receiving private data about the user or making changes to the user’s data.

There are strategies for avoiding this type of attack vector. One is to check the origin of all connection requests—our application should only allow connections from domains that it knows about. A different strategy includes a CSRF token that proves that the user visited the application properly.

The strategy that we’ll use in this course is not to use cookies when authenticating our WebSocket. Instead, we’ll use a signed token to provide a user session to our Socket. Our front-end client will pass a secured signed token in the connection parameters upon connection to a Socket. Our application will verify that the token originated from one of its servers and was generated within a given period.

We will code a Socket authentication example by laying out the skeleton of our Socket and then implementing the authentication logic. First, let’s add our new Socket to our Endpoint. Enter this code after the existing socket/3 function call:

Get hands-on with 1400+ tech skills courses.