6
votes

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.

2

2 Answers

19
votes

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.

0
votes

The privacy of SSE data is really dependent on algorithm you design.

Basically, the browser can reaching connection via URL without a hidden KEY & ID : new EventSource('XXX");

Putting KEY-ID to URL is still has highly exposure risk.

It's good to design some hidden deal between server and client to secure the stream data:

  • Add a counter on server to allow only 1 SSE receiver connect. Each connection have a different address.
  • Encrypt data with a key which the key is shared in a safer transferring method. (POST XMLhttp)
  • Display content in an iframe with sandbox
  • Recognize client device configuration (OS, browser) to filt other device.