3

I have a working .NET website with authentication up and running (Identity 2.0 via Owin & https://identityazuretable.codeplex.com/)

I would like to use websockets primarily for the SignalR transport, but because the domain is running on cloudflare (the free plan does not currently support websockets) I cannot use SignalR on the same domain and get websockets. So to work around this issue I have a subdomain websockets.example.com, which does not use cloudflare, but does point to the same application.

However, I now wish to authenticate the SignalR connections based on their forms authentication token in a cookie. However the cookie does not get sent when I do the below, or when SignalR connects to websockets.example.com

JQuery Request:

$.ajax({
   url: "//websockets.example.com/signalr/hubs",
   type: "POST",
   xhrFields: {
         withCredentials: true
   }
});

Or:

$.connection.hub.url = '//websockets.example.com/signalr/';
$.connection.hub.start({ withCredentials: true });

Headers:

Accept:*/*
Accept-Encoding:gzip,deflate
Accept-Language:en-GB,en-US;q=0.8,en;q=0.6
Connection:keep-alive
Content-Length:0
Cookie:ARRAffinity=805c328533b85a33c6fdeb4870bd41f00e05fd898b5d784f2635656f9525466b
Host:websockets.example.com
Origin:http://example.com
Referer:http://example.com/Page

Response:

Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin:https://example.com

EDIT: Owin Config:

app.Map("/signalr", map =>
            {
                map.UseCors(new CorsOptions
                {
                    PolicyProvider = new CorsPolicyProvider
                    {
                        PolicyResolver = context =>
                        {
                            var corsPolicy = new CorsPolicy
                            {
                                AllowAnyHeader = true,
                                AllowAnyMethod = true,
                                SupportsCredentials = true,
                                AllowAnyOrigin = false,

                            };

                            corsPolicy.Origins.Add("http://example.com");
                            corsPolicy.Origins.Add("http://www.example.com");
                            corsPolicy.Origins.Add("http://websockets.example.com");
                            corsPolicy.Origins.Add("https://websockets.example.com");
                            corsPolicy.Origins.Add("https://example.com");
                            corsPolicy.Origins.Add("https://www.example.com");
                            return Task.FromResult(corsPolicy);
                        }
                    }
                });
                map.RunSignalR();
            });
Mike Wade
  • 1,646
  • 15
  • 28

1 Answers1

3

I think your issue is with the way your authentication cookie is set. This would explain why the cookie isn't sent to websockets.example.com via SignalR or a normal CORS request made via jQuery.ajax.

To ensure cookies set by a parent domain are sent to submdomains you need to explicitly define the domain with the Set-Cookie header:

Set-Cookie: name=value; domain=.mydomain.com

If you don't explicitly define the domain, cookies will only be sent back to the exact domain that set them.

http://erik.io/blog/2014/03/04/definitive-guide-to-cookie-domains/ https://stackoverflow.com/a/23086139/719967

Community
  • 1
  • 1
halter73
  • 14,442
  • 3
  • 44
  • 54
  • Sounds good - I actually ended up implementing a work around using SignalRs caller state (as the page that loads signalR loads from the domain where authentication works). – Mike Wade Nov 27 '14 at 15:02