Flowing Identity from a Client to a Service when using RESTful WCF Part 1 – The Problem

September 1, 2008

The digital representation (or identity) of users accessing connected applications will be increasingly modeled using the the concept of Claims. If you’re workingimage with SOAP based web services then the problem of how to implement claims based access control into your WCF services is is a fully solved problem. Whether or not you are using the new Zermatt framework or the claims based identity support in the System.IdentityModel namespace there exists plenty of guidance, available on the web and in books, to help you get everything wired together in a predetermined way. If you’re writing a REST API, however, things aren’t so simple.

SOAP vs REST in WCF – who cares? A service is a service, right?

All of the claims based security support in WCF relies on SOAP envelope headers to transmit a user’s claims from the service consumer to the service. This is to be expected, as several WS-* specs play an important role in WCF’s security support. As a result, if you are using a SOAPless WCF binding such as the RESTful WebHttpBinding, the best you can get for free is transport level security. That means you’re pretty much limited to transmitting authentication credentials, such as a username/password pair (via Http Basic Auth) , a Certificate, etc. If you have a security token containing claims you’d like to pass along, such as a SAML token, it isn’t immediately obvious how to flow that token from the service consumer to the service provider.

Hey, SOAP doesn’t have a patent on Envelopes!

In a RESTful API there is no “envelope” inherent in the message payload itself like there is with SOAP messages.  Indeed, when retrieving data from a RESTful service, there is no message payload at all. The entire scope of a GET request is communicated via the URL. Unlike SOAP, however, the transport protocol you will be using with REST is not a configurable, deploy-time variable. REST operates over HTTP by definition, and the HTTP protocol specifies its own message envelope that supports message headers. These are just the standard, everyday HTTP headers you already know and love. Therefore, we decided the best place for a security token to be stashed when working with RESTful WCF was in a custom HTTP header.

Where do you get a security token from in the first place?

Actually, I’m not going to go into how you go about authenticating a user and obtaining a claim-laden security token (usually a signed, encrypted SAML token). Zermatt should be able to help out with this (see this post for how), and there are also inexpensive .NET libraries you can buy that will abstract away the yucky cryptography/SAML aspects of creating and consuming a proper token. You can even leave these details until the Last Responsible Moment if you want, and, like we are doing, stub out the process of building or obtaining a proper interoperable token and temporarily substitute a simple plain text, character-delimited or XML serialized list of claims to getting everything working and tested and then plug in the gory details later in the process when you’ve selected a vendor/platform/framework as your Security Token Service (STS). For more info on building or buying an STS, see here and here.

The problem distilled

So that leaves us with only a single problem: how do we send a custom HTTP Header containing the logged in users security token with each service request without giving up the convenience of runtime-generated proxies via the WebHttpChannelFactory? Ok, there is another (small) part to the problem: how do we read this custom header on the service side of the wire early enough in the WCF lifecycle so we can unpack the embedded claims and make them available to the service implementation for making authorization decisions?

WCF Extensibility to the rescue!

The specifics of the solution, and code samples, will be presented in the next post.

Share: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • del.icio.us
  • DZone
  • Digg
  • Google Bookmarks
  • Ma.gnolia
  • Technorati
hello
blog comments powered by Disqus