12 July 2010
Using the WCF Authentication Service without cookies
One of the most straightforward ways of securing web services for a Silverlight client involves leveraging ASP.NET Forms Authentication to provide cookie-based security. It’s a convenient and robust means of adding declarative role-based security to web services that involves exposing the .NET Authentication Service as a set of web methods.
However, what happens when you want to access these services using a console application or WPF client?
The WCF Authentication Service relies on cookies to maintain the link between client and server. An authenticating cookie is sent down to the client when the user logs in and sent back to the server for each subsequent data request.
This is fine if you are using a client that keeps an HTTP context on the go – i.e. an ASP.NET or Silverlight client – but if you use a client without an HTTP context – such as a console application or WPF client – then any attempt to access secured services will give you an “Access Denied” error.
If you use an HTTP debugger such as Charles you can see what’s going on with the requests. A cookie is being returned by the authentication service, but nothing is being sent in the header to the secured data services so the services are unable to authorise the call and allow access to the service.
The solution is to manage the cookie manually, accepting it from the authentication service and sending it back with each web service call.
Given the WCF provides access to pretty much any part of the SOAP message this is pretty straightforward. It all relies on using the OperationContext class to gain access to the headers where you can read and write the cookie.
The code sample below shows how to extract the authentication cookie that is returned by a call to the WCF Authentication Service:
Note the use of the FormatCookie() function – this is a piece of code that formats the cookie received from the authentication call into something that you can send back to secured methods. It just removes the path and expires arguments.
Finally, you can send the formatted cookie into a call made to a secured data service and your security context will be picked up: