Securely consume WCF data services in Silverlight applications.

Microsoft has made Windows Communication Foundation (WCF) very attractive by providing tools that make the development of WCF web services extremely easy. Even WCF Data Services that provide the interation with complicated databases can be constructed literally in minutes. Consuming WCF services are also made easy by proxy client classes that Visual Studio can automatically generate in seconds.

It is very surprising how much hassle it is when one tries to secure WCF services even for the simplest scenario. Just look at the 8-article long series on WCF Data Services authenticaion by the WCF Data Services team at Microsoft.  Suppose one has a WCF data service that is made specifically for one Silverlight app, so it allows only the Silverlight application to access it.  Many steps are required even for this simple scenario.  Tejada has a great article on Securing OData Services using Forms Authentication.  

Here are the summary of the steps for aformentioned simple scenario:

  1. Create the WCF data service.
  2. Configure Forms Authentication, and set up membership service in the host's web.config.
  3. Secure the service file (e.g. foo.svc) by adding a corresponding <location> element in the web.config, and add an <authorization> element to allow only one user (e.g. "slapp") to access it.
  4. Create a Silverlight-enabled WCF service for authentication.  This is the key.  The idea of this is to allow Silverlight apps  to log in with credentials first, so subsequent calls to the WCF data service will use the same credentials automatically (i.e. send authentication cookie in each call). Remove the .cs file of the service, and replace the content of .svc file with online <%@ServiceHost Language="C#" Service="System.Web.ApplicationServices.AuthenticationService" %>
  5. Add a  <system.web.extensions> element to the web.config.
  6. Replace the <service> element in the web.config created by VS automatically when the Silverlight-enabled service was created with an element for System.Web.ApplicationServices.AuthenticationService.
  7. Change the <binding> element of the Silverlgiht-enabled service to use HTTPS.  This is important.  Not using HTTPS makes the whole effort almost meaningless.
  8. In the Silverlight app, call the authentication service to log in with the user name and password.
  9. Only after the authentication is successful, start using the WCF data service without any extra work

For details, please refer to section Silverlight 4 of Tejada's article.

Unfortunately, System.Web.ApplicationServices.AuthenticationService is a shaky component. It may not work under some circumstances.  Since it is like a black box for its users, it may be better to skip it if it turns out not working reliably.  Trying to get it work by trial and error may cost many hours to no avail.  It may take just minutes to implement one's own WCF data service security scheme by by extending DataServiceContext on the client side (hooking into SendingRequest handler), and extending DataService on the server side (hooking into OnStartProcessingRequest()).

When extending the DataServiceContext of the client reference, it is very important to do it by defining the partial class in a separate file instead of modifying the file created by VS automatically.  Otherwise updating the service reference would remove all the custome code.