0
votes

I followed This Thread, but I as I have not fully understood the answer in my case, I would like to post again.

I am using EventSource in my Front-End and the Backend is using echo event to stream data relatively to a drone to my application.

var source = new EventSource(`blabla:3000/sse?channel=myProject${projectID}`);
source.addEventListener(`myDrone${droneID}`, function(e){
    console.log('Received an update message:', e.data);
});

In the backend, by default nothing is streaming, and a user on connection will request to the backend to start emitting events. This call is secured using jwt_token. So to make the server start stream, a token is needed.

The question I have is, when a server is already streaming.

Let's say I am a not connected (so no valid token), and I decided to connect to the SSE stream because I know the channel name and the server is already streaming. If I start a new EventSource on blabla:3000/sse?channel=myProject${projectID}. Would I still be able to see all of the message sent trough this channel? I believe that yes.

How is it possible to secure those event streamed to be only on registered user ?

Ex : (read from top to bottom)

enter image description here

How can I prevent a user that know the channelName to receive all the event stream by the server ?

Since the front end and backend are hosted on the same domain at the moment, but this might change, so I need a broad answer.

1
Can you expand on "when a server is already streaming, If I am a not connected". Every stream is dedicated to one connection in SSE, so connected and streaming always go together. But I think you might be talking about something different?Darren Cook
When a client connect to the channel, the server will initiate a stream on the channel and keep streaming until all of the host disconnect. During that phase, there is a auth check. But once the channel is open and the server is streaming, I believe it is possible for anyone so open an SSE connection with the correct channel name and listen to all messagesBobby
I think it might help if you can update your question with a diagram showing the components and data flow.Darren Cook
@Bobby are you using https://github.com/EventSource/eventsource?Majoris

1 Answers

1
votes

It depends on how you set up your SSE server and whether or not you're looking for authenticated users. You'd need to configure your echo server to handle authentication by using Go's http.Handler

Once you do that, then doesn't matter if you know the channel name and the server, the backend can still reject sending messages to users without tokens. Don't think of it as a token as what is used to create a channel, rather think of it as a request to subscribe is what's needed - and then depending on whether the request is authenticated or not, the service will then either allow or reject. The push service should be continuously doing this for all subscription requests.

The server is what issues to the token upon authentication, and once you receive your key, you can let the server know that you've registered by appending the token as a querystring parameter named "key", or you can provide a header within your request. Here's how:

var key ='xVLyHw.HSvCPg:d1RaNTqnY3s4EZZh';
var url ='https://realtime.ably.io/event-stream?channels=myChannel&v=1.1&key=' + key;
var eventSource = new EventSource(url);

eventSource.onmessage = function(event) {
  var message = JSON.parse(event.data);
  console.log('Message: ' + message.name + ' - ' + message.data);
};

example taken from: https://www.ably.io/documentation/sse

You can also receive an auth token, and you can pass that into your "accessToken" querystring - similar to how you do it with the key in the above example. But mind you, you can literally copy and give this key to anyone out there, and then they can listen to the same channel. You can also save the auth token into localstorage, and pass it as a header. You can use this library to achieve this:

var EventSource = EventSourcePolyfill; 
const eventSource = new EventSource(`blabla:3000/sse?channel=myProject${projectID}`,{
  headers: {
    'Authorization': 'my secret jwt token' // or localStorage.getItem("myToken")
  }
});

Library for added headers is found here: https://github.com/Yaffle/EventSource

Or you can use the basic auth that can generate a cookie, and send the request to subscribe along with the cookie by setting withCredentials = true:

var source = new EventSource(`blabla:3000/sse?channel=myProject${projectID}`, { withCredentials: true });