2
votes

I am trying to setup servicestack with ServerEvents. I have added the plugin for ServerEventsFeature. I am using the Javascript server events client and I tried a simple example by doing this on the client after the user was authenticated.

  var source = new EventSource('http://localhost/ecmapi/event-stream?channel=MyChannel');
  $(source).handleServerEvents({
           handlers: {
                  onConnect: function (subscription) {
                       console.log("connected! welcome " + subscription.displayName);
                  }, 
                  onHeartbeat: function (msg, e) {
                      //console.log("onHeartbeat", msg, e);
                       },
                  showNotification: function (type, e) {
                        console.log("showNotification", type);
                        } 
                  }
           });

On the apphost file:

            Plugins.Add(new ServerEventsFeature
                   {
                       StreamPath = "/event-stream",           
                       HeartbeatPath = "/event-heartbeat",     
                       UnRegisterPath = "/event-unregister",    
                       SubscribersPath = null, 
                       LimitToAuthenticatedUsers = false, 
                       NotifyChannelOfSubscriptions = false
                   });

To send an event to client I am calling:

ServerEvents.NotifyChannel("MyChannel", "cmd.showNotification", message);

And I successfully receive it on the showNotification function on the client.

However, the subscription.displayName is auto generated and is not related to the currently logged in user. Also, if I set the LimitToAuthenticatedUsers to true then a 401 error is retruned.

My question is, what else is needed so that the javascript server events client can work with the user that is already logged on? I will want to use the ServerEvents.NotifyUserName or ServerEvents.NotifyUserId function instead and also only allow authenticated users to subscribe.

Thanks!

** The request and response headers for auth and EventSource as requested **

Request auth

POST http://localhost/ECMAPI/auth.json HTTP/1.1 Accept: / Content-Type: application/json X-Requested-With: XMLHttpRequest Referer: http://localhost/InterfaceGov/Default.aspx Accept-Language: en-gb Accept-Encoding: gzip, deflate User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0) Host: localhost Content-Length: 43 Connection: Keep-Alive Pragma: no-cache Cookie: _ga=GA1.1.2077781525.1452005918; .ASPXANONYMOUS=hOL_MQPsZk5z5t31805S8oazFP0IdbeHKBejAH2x2Ic6hS5070aWW5A-2dklH10qT8IE9pshiAgUkmwN-TfVXjXUhAYVaWKzuOIyCy1nE8VAdETQk1TqB_39gk5ST8cIcvO2KNgB8d5h1f38W8hIzg2; ss-pid=hMBothYg2ETWObMTMJDY; ss-id=x9zxOTH2rFxLo8tO01Nw

Response auth

HTTP/1.1 200 OK Cache-Control: private Content-Type: application/json; charset=utf-8 Vary: Accept Server: Microsoft-IIS/7.5 X-Powered-By: ServiceStack/4.038 Win32NT/.NET Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS Access-Control-Allow-Headers: Content-Type, Authorization X-AspNet-Version: 4.0.30319 Set-Cookie: ss-pid=QjEKGQphtPJZjZJmPtCt; expires=Sun, 11-May-2036 12:18:29 GMT; path=/; HttpOnly Set-Cookie: ss-id=1yKLtkiTD2NshpiPrffu; path=/; HttpOnly X-MiniProfiler-Ids: ["1d0459ec1fad4695ac0f3c7fc69cad0a","3f5cd3515e084363b86df1e54633a683","0f54d87508594cba9757660dc664aeef"] X-Powered-By: ASP.NET Date: Wed, 11 May 2016 12:18:30 GMT Content-Length: 17514

Request EventSource

GET http://localhost/ecmapi/event-stream?channel=MyChannel HTTP/1.1 Accept: / Origin: http://localhost Accept-Language: en-GB Accept-Encoding: gzip, deflate User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0) Host: localhost Connection: Keep-Alive Pragma: no-cache

Response EventSource

HTTP/1.1 401 Unauthorized Cache-Control: private Vary: Accept Server: Microsoft-IIS/7.5 WWW-Authenticate: credentials realm="/auth/credentials" X-Powered-By: ServiceStack/4.038 Win32NT/.NET Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS Access-Control-Allow-Headers: Content-Type, Authorization X-AspNet-Version: 4.0.30319 Set-Cookie: ss-pid=c0UQXy4YJNQmVuUiEVfA; expires=Sun, 11-May-2036 12:18:30 GMT; path=/; HttpOnly Set-Cookie: ss-id=y9e8BbD1na5EoHu8GUug; path=/; HttpOnly X-MiniProfiler-Ids: ["1d0459ec1fad4695ac0f3c7fc69cad0a","3f5cd3515e084363b86df1e54633a683","0f54d87508594cba9757660dc664aeef","f1584abd58e64a9dac6ceceaa932c47a"] X-Powered-By: ASP.NET Date: Wed, 11 May 2016 12:18:30 GMT Content-Length: 0

1
Can you also provide code from your AppHost where you add and configure the ServerEventsFeature to Plugins?Darren Reid
@Layoric I have updated my question and included the plugins configurationNicolas I
Could you double check that your users in your IUserAuthRepository users have the DisplayName value populated. If this is null it might be still using the generated value. Also, if you want to restrict to only authenticated users use the LimitToAuthenticatedUsers flag in the ServerEventsFeatureDarren Reid
@Layoric the user generated by the client is entirely different than the one accessed from the server using GetSession(). Thus, if I set the flag to true then a 401 error is returned. If you see the chat example here github.com/ServiceStackApps/Chat then it is also auto generating users.Nicolas I
I'm not sure where you are calling GetSession(). With what you've shown I can't reproduce the problem. I have a simple SSE with auth showing anon and authed usernames are being logged on the client correctly with associated auto user or anon. LimitToAuthenticatedUsers Also only logs the onConnect when using an authenticated user. Hopefully this will help narrow down the issue.Darren Reid

1 Answers

2
votes

The reason why /event-stream returns a 401 Unauthorized is because your request to /event-stream does not contain the necessary Session Cookies which is what establishes an Authenticated request.

This is only an issue in IE since it's the last remaining browser that doesn't have native support for Server Sent Events and requires a SSE shim to work where one of its limitations is that it doesn't send Session Cookies.

The default_ieshim.cshtml in the http://chat.servicestack.net/default_ieshim Live Demo shows how to support Authenticated Requests in IE as well by instead appending the ss-id sessionId to the event stream url which you can populate in a Razor page with:

var source = new EventSource(
  '/event-stream?channels=@channels&ss-id=@(base.GetSession().Id)&t=' 
  + new Date().getTime());

You also need to tell ServiceStack to accept Session Id's in the Url which you can do in your AppHost's Configure() with:

SetConfig(new HostConfig {
    AllowSessionIdsInHttpParams = true,
});