Authentication with ServerEvents

I have a typical SS service (ServiceA), and it publishes certain events over certain channels using an SSE server (through IServerEvents).

I have another typical SS service (ServiceB), that wants to consume SSE events on one or more of the channels.
I want to secure the connection between SEE client (serviceB) and SSE server (ServiceA).

Now, ServiceA already uses the AuthFeature and it is configured with a custom AuthProvider that is a IAuthWithRequest, that PreAuthenticates and inspects the Bearer token of each request.

My question is: How do I configure my SSEClient in ServiceB to connect with Authentication to the SSE Server in ServiceA?

This is how I create my SSE client now in ServiceB:

                this.serverEventsClient = new ServerEventsClient(baseUrl, Channels.All);
                this.serverEventsClient.RegisterReceiver<GlobalReceiver>();

                container.RegisterAutoWiredTypes(this.serverEventsClient.ReceiverTypes);
                this.serverEventsClient.Resolver = container;

                this.serverEventsClient.Start();

What am I missing?

This scenario is pretty hard to follow…

But I’m going to assume by ServiceB you mean an SSE client that wants to connect to a ServiceStack Server (ServiceA).

The ServerEventsClient uses the pre-configured client at client.ServiceClient where SSE Client authentication is the same as it is for a normal C# Service Client where you’d just need to authenticate with the embedded C# ServiceClient as we can see with the implementation of ServerEventsClient.Authenticate() which just authenticates the pre-configured ServerEventsClient.ServiceClient by sending a Authenticate DTO as normal:

public static AuthenticateResponse Authenticate(this ServerEventsClient client, Authenticate request)
{
    return client.ServiceClient.Post(request);
}

Which if successful will populate the ServiceClient with ServiceStack’s Session Ids - establishing an authenticated connection.

client.ServiceClient.Post(new Authenticate { ... });

BTW if you need to, you can specify a client.EventStreamRequestFilter to modify the client HttpWebRequest and add any required headers needed when establishing the SSE Connection.

Thanks,

Woops, I forgot to say that my custom AuthProvider in ServiceA only needs to see a bearer token in the Authorization header to perform authentication. (it gets that by calling req.GetBearerToken().

So my question is how would I construct an new Authenticate() DTO in this case? with just a bearer token?

BearerTokens needs to be sent with the HTTP Headers (i.e. not in the Authenticate DTO), so you can try:

client.EventStreamRequestFilter = req => req.AddBearerToken(bearerToken);

hi demis, how does this work with the typescript-client?

i tried it with:
this.sseClient.serviceClient.bearerToken = this.tokenManager.getAccessTokenBase64();

but it seems that the ServerSentEventsClient doesn’t use the underlying serviceClient to send. Or am i missing something?

EDIT:
i looked at the index.ts. As far as I see there is no functionality to set the bearer token. in our case, we don’t own the auth services. would be nice to be able to do that.

The TypeScript ServerEventsClient needs to use the browsers native EventSource class to establish the SSE connection so it doesn’t have the same ability to customize the HTTP Request connection that EventStreamRequestFilter is able to.

However the browser shares the same cookies with all ajax requests to the same host so if a ss-tok Cookie is added to any request to that domain, all ajax requests to the same host should contain the same cookies (CORS permitting).

So you can try setting the JWT Token Cookie on the client with:

document.cookie = "ss-tok={Token}";

thats what we ended doing since protected image loading in img tags also doesnt work with bearer token in header either.

thank you again!

Hey @mythz, we’ve been trying to get server-side events to work with authentication and had no idea why it wasn’t working with a bearer token until we found this explanation.

It would be nice to add a section about JWT authentication with the TS client to the documentation so others can find this more easily. Or maybe there is a sample and we just missed it?

The latest v5 release notes shows other solutions: http://docs.servicestack.net/releases/v5.0.0#send-jwts-in-http-params