WebSockets-specific security practices: JSON Web Tokens
When using the WebSockets protocol, there are a lot of potential pitfalls to bear in mind that can be very confusing to really get your head around from a security standpoint.
There's no real "authentication system" in WebSockets
In a normal HTTPS scenario, you request a page, and when the authentication is complete, the page is delivered. If you want any other content - e.g. some new result loaded from an AJAX request - you have to authenticate again with a new HTTPS request.
WebSockets, by contrast, are sort of designed to avoid this exact problem: the overhead associated with every new request involving another authentication handshake with the server. Instead, you connect once, and the user remains connected for the duration of the WebSocket connection, which generally lasts until a disconnection occurs on either side.
This presents several security challenges, which aren't the fault of WebSockets itself but are something you still have to account for.
The problem of authenticating a user in WebSockets
On your website, a user has a login session, that is held by your webserver (or more commonly, by a cache server that holds sessions for all your webservers in one place).
Your WebSockets server, however, has no notion of this session. It doesn't know your user is logged in; you have to authenticate them. You can't pass it the session ID of the user's webserver session, because for security reasons that ID is going to be regenerated frequently. So what do you do?
Authenticating via JSON Web Tokens (JWTs)
To authenticate your user, you need to provide some form of proof that they are logged in on your webserver, i.e. that they should be allowed to connect to the WebSockets server. To do this, you could use a standard AJAX request that goes off to your webserver, checks the user is logged in, and if so, generates a JWT the user can pass to your WebSockets server as authentication.
There are lots of different libraries to easily make use of JWTs; you can find a large list of them on the jwt.io website.
Not just authentication... but re-authentication
As mentioned above, you also need to account for the problem that a user's webserver session doesn't last forever, and so you are going to need to re-authenticate your user to your WebSockets server at regular intervals to show they are still logged in. This is important for two reasons.
Firstly, without this, the webserver is basically accepting a one-time authentication to send events for a potentially very long time, even when the user may no longer be authenticated. Secondly, although you can implement client-side code to log out your user from the WebSockets server when they log out of your webserver, this doesn't cover all cases: your user might be logged out of the webserver for inactivity, and it would not be able to notify the user of this, so the WebSockets server would keep them logged in until the next reauthentication interval. In addition, the client-side code could be overridden to not trigger the logout, so it can't be relied upon.
As such, you need to implement a periodic re-authentication in your client-side code, that makes a new AJAX request to the webserver for a JWT and passes it to the WebSockets server to show it's still authenticated. You may also want to limit how long this can happen on a single page without the user moving to a new page or performing some action, to prevent continual reauthentication on e.g. some tab that's been forgotten about.
You will also need to implement a bit of server-client communication, whereby the WebSockets server disconnect a user who has not re-authenticated within some time period, and gives them the message that they need to re-authenticate to continue receiving messages. Your client-side code then needs to perform this reconnection and re-authentication.
Be aware that WebSockets sessions are generally per browser tab, not per browser instance or user session. You will need to keep a record in the user's local browser storage of whether they have an active WebSockets session to your WebSockets server, or else you will end up having multiple sessions open for the same user, which is inefficient and can cause security vulnerabilities if you do not close all the sessions correctly on a user logging out.