Securing WCF Data Services using WIF

This questions comes up every once in a while..

Since WCF Data Services is just a normal WCF service (using the web programming model), all the typical security APIs and extensibility points apply.

That said, depending on your scenario you might have to be a little more creative for REST-style services. Here’s a quick walkthrough:

Enabling WIF in the Data Service
The easiest way to get WIF wired up is by writing a custom service host factory. You simply have to derive from DataServiceHostFactory, override CreateServiceHost and call FederatedServiceCredentials.ConfigureServiceHost before you return the host to the plumbing.

This gives you the standard WIF integration for all standard HTTP credential types (Basic, Integrated etc…) and the typical extensibility points like ClaimsAuthorizationManager.

For accepting and converting more advanced token types like SWT or SAML, you need to plugin your own token handling. I gave it a try for SWT tokens (see here for the general SWT integration story).

public class ProtectedDataServiceHostFactory : DataServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(
      Type serviceType, Uri[] baseAddresses)
    {

        var host = base.CreateServiceHost(serviceType, baseAddresses);

        host.Authorization.ServiceAuthorizationManager = new
          SimpleWebTokenAuthorizationManager(
             acsAddress,
             expectedAudience,
             acsKey);
        host.Authorization.PrincipalPermissionMode =
          PrincipalPermissionMode.Custom;

        return host;
    }
}

This uses my SWT plumbing to turn incoming SWT tokens into an IClaimsPrincipal. You could easily do the same thing for SAML (but be aware that SAML tokens can become quite big – and you typically want to transmit them using an HTTP header for this scenario).

You could now use the resulting claims for authorization as well as WCFDS interceptors, e.g.:

[QueryInterceptor(“Users”)]
public Expression<Func<Users, bool>> OnQueryUsers()
{
    var principal = Thread.CurrentPrincipal as IClaimsPrincipal;
    var customer = principal.GetClaimValue(“http://claims/customerName&#8221;);

    return user => user.Applications.ApplicationName == customer;
}

Sending a token header to the Data Service
The next step is to send a token to the Data Service. This can be achieved by handling the SendingRequest event on the DataServiceContext derived client plumbing, e.g.:

class ProviderEntitiesWithToken : ProviderEntities
{
    string _token;
    string _tokenHeader = “Authorization”;
 
    public ProviderEntitiesWithToken(Uri address, string token) : base(address)
    {
        _token = token;
        SendingRequest += OnSendingRequest;
    }
 
    void OnSendingRequest(object sender, SendingRequestEventArgs e)
    {
        e.RequestHeaders[_tokenHeader] =
          SimpleWebToken.GetAuthorizationHeader(_token);
    }
}

Using the Data Service
The usage pattern is the same as without any tokens or WIF. New up your derived class, set the token and use e.g. LINQ to query the Data Service.

static void Main(string[] args)
{
    var token = RequestToken();
    var service = new ProviderEntitiesWithToken(new Uri(dataServiceAddress), token);
   
    var users = from u in service.Users
                select u;
 
    users.ToList().ForEach(u => Console.WriteLine(u.UserName));
}

HTH

This entry was posted in IdentityModel. Bookmark the permalink.

1 Response to Securing WCF Data Services using WIF

  1. Pingback: Claims-based authentication for WCF RESTful services - Tech Forum Network

Leave a comment