Cookie problems when using federated security and SignalR

I recently ran into a problem where the application I was working on didn’t pass the security information as expected to the server. The application in this case is a Silverlight client, with a WebAPI and SignalR backend. For security, we are using WIF…or federated security…I don’t know what to call it anymore. We aren’t really federating it today, but it is based on the same framework…

It has been a while since I was involved in the system, but I got roped back in to solve some issues. And while doing so, I discovered that I wouldn’t get a proper security context for calls made from the client to the server using SignalR. For some reason, those calls where just not being authenticated properly…

So I pulled up Fiddler to have a look at what was actually being sent to the server. As the security works using an encrypted cookie being sent back and forth, I assumed that there might be something wrong in that part of the communication. And there was. No cookie was being sent to the server…something that I had seen a couple of times before…

To be able to get Silverlight to properly handle cookies, you have to tell it what CookieContainer to use, which we were already doing for all our WebAPI calls. However, SignalR didn’t seem to be catching on to this.

For our WebAPI calls, I have created a custom implementation of IWebRequestCreate that looks like this

internal class CustomWebRequestCreator : IWebRequestCreate
{
private static readonly CookieContainer Container = new CookieContainer();

public WebRequest Create(Uri uri)
{
var request = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(uri);
request.CookieContainer = CookieContainer;
return request;
}

public static CookieContainer CookieContainer { get { return Container; } }
}

As you can see, the implementation of Create() uses the WebRequestCreator.ClientHttp .Create() method to create a new WebRequest. It then makes sure that it uses a CookieContainer, which is stored in a static variable, making it available to the entire application, throughout the entire lifetime of it. Basically, making sure that every single WebRequest ever created using that IWebRequestCreate implementation, will share the same cookie container.

I have then set up the system to use that implementation for all calls to urls starting with http or https. This is done during application startup, using these lines of code

var webRequestCreator = new CustomWebRequestCreator();
WebRequest.RegisterPrefix("http://", webRequestCreator);
WebRequest.RegisterPrefix("https://", webRequestCreator);

This solution is working perfectly for all the WebAPI calls, but due to the way that SignalR works, that CookieContainer isn’t used properly for SignalR calls.

However, SignalR exposes a CookieContainer property on the HubConnection class. And by setting this to the proper CookieContainer, I got cookies flowing again. The code looks something like this

var connection = new HubConnection(address);
connection.CookieContainer = CustomWebRequestCreator.CookieContainer;

In this case, the client was a Silverlight client, but I do believe the same solution would be needed for other non-web clients, such as WPF and WinForms, as well.

Add comment