Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EventSource / SSE (Server-Sent-Svents) - Security

I have read through the w3 spec @ http://www.w3.org/TR/eventsource/ for how EventSource/SSE works, but I cant find any good information about how a private stream should be created.

Basically, I want to create a way to send private data to specific user-sessions. Both the ideas below seems to do what I want, but I am not so sure how secure they are.

Example; does every browser connecting to the same EventSource URL receive the same data, and the browser keeps track of what event-name it wants?

var source = new EventSource('/stream');
source.addEventListener('l0ngr4nd0mSessionID', function(e){
    console.log('Received a private message:', e.data);
});

Will anyone without the event-name of l0ngr4nd0mSessionID be able to get this message?

What about this case;

var source = new EventSource('/stream/l0ngr4nd0mSessionID ');
source.addEventListener('private', function(e){
    console.log('Received a private message:', e.data);
});

Is these examples just as good as setting the withCredentials option? My sse server is a seperate server than the main web-server, so I would prefeer to not send authentication-data using withCredentials and rather use one of the examples.

like image 647
xeor Avatar asked Dec 02 '13 09:12

xeor


People also ask

How many SSE connections can a server handle?

SSE has a variety of features that Websockets lack by design, e.g., automatic reconnection, event ids, Only Websockets can send both binary and UTF-8 data, SSE is limited to UTF-8, SSE suffers from a limitation to the maximum number of open connections (6 per browser + domain).

How do SSE events work?

SSE is designed to use the JavaScript EventSource API in order to subscribe to a stream of data in any popular browser. Through this interface a client requests a particular URL in order to receive an event stream. SSE is commonly used to send message updates or continuous data streams to a browser client.

Are Webhooks server sent events?

When should I use Server Sent Events as opposed to Webhooks? Webhooks requires a server side subscription, meaning that you need an HTTPS endpoint to create the subscription. On the other hand, Server Sent Events subscriptions can be created on the client side.

How does SSE work under the hood?

Under the hood, SSE provides an efficient, cross-browser implementation of XHR streaming; the actual delivery of the messages is done over a single, long-lived HTTP connection.


1 Answers

Each stream is private. SSE is not a broadcast technology (unless you deliberately implement it as such). Instead each browser client is given a dedicated socket connection to your server. Your server will use a concurrent event handler to deal with just that client, and will choose what information it wants to send to that client. You get that client's cookies too, so can identify their session, and basic authentication also works.

Everything gets much more complex when CORS gets involved, i.e. if your SSE server is not the same origin as where the HTML was served from. That is the situation you described. Your server will have to send back "Access-Control-Allow-Origin: *", but you do not need to use withCredentials if you are happy to send that unique sessionID. But note that you will not get cookies or basic auth data.

Going back to your question, the first example is bad. It implies your server is broadcasting private data to all clients. As well as the privacy issue, that is also a horrible waste of bandwidth.

Your second approach is better: you are using something in the URL to identify the data the user should receive, in lieu of using a cookie or authentication. Note that anyone who knows this URL can get the same data. SSL will not help. I'm guessing your session ID is something that they get when logging in to your main web site, and that it expires when they log-out. For most situations I think this is Good Enough: a hacker has to go to quite a lot of trouble for a relatively short window of access. In other words it is easier to use social engineering to get the user's auth details. But you need to do your own risk/benefit evaluation.

The most secure approach is to use SSL with cookies or basic auth. This is easy if web server and streaming server are the same origin; otherwise you need to use withCredentials.

like image 107
Darren Cook Avatar answered Oct 08 '22 14:10

Darren Cook