Sergey Shishkin

on agile software development

Archive for February 2007

CardSpaceSelector: Working with Windows CardSpace API

Writing CardSpace-enabled application is easy – WCF has a feature-rich WSFederationHttpBinding binding for client-server scenarios, and the browsers (IE7 and Firefox) support special HTML markup to call a CardSpace selector from within a web page. Both these scenarios are well documented and implemented in many good samples available on the net. In addition, Windows CardSpace provides an unmanaged API (infocardapi.dll) and a managed wrapper for that API. Unfortunately, there is a lack of information and almost no samples covering the API.

The managed API is represented by the System.IdentityModel.Selectors.CardSpaceSelector class, which has three public methods: Manage, Import, and GetToken. The Manage method has no parameters and, when called, opens a Windows CardSpace selector allowing the user to manage his information cards; the same as to run the Windows CardSpace control panel applet. The Import method receives a string parameter—path to the information cards backup file to be imported—and, when called, opens a selector to offer the user to import information cards; the same as to open a ‘.crds’ file in windows explorer. The third method—GetToken—is much more complicated and, at the same time, is the most interesting one for developers.

The purpose of the GetToken method is obvious from its name. The method has two overloads. One of them calls internally its more general overload and therefore we will look in more details only at the general case. The GetToken method receives an array of CardSpacePolicyElement objects and a SecurityTokenSerializer. The latter is an abstract class; however, one can pass an instance of the System.ServiceModel.Security.WSSecurityTokenSerializer class as a serializer to the GetToken method. An array of policy elements represents a federation chain of identity issuers. In the simplest case there will be only one element in the array representing the security token service (STS).

To create an instance of the CardSpacePolicyElement class one need to pass to the constructor the following parameters:

  • XmlElement target. The endpoint of the recipient of the token – the relying party (RP). This should be valid WS-Addressing XML for an endpoint reference. The easiest way to build the required XML is to use System.ServiceModel.EndpointAddress class. Use its object model to create an instance and then call one of its WriteTo methods. Note that an EndpointIdentity is required for the recipient’s EndpointAddress.
  • XmlElement issuer. The endpoint of the token issuer – STS. This should be a WS-Addressing endpoint reference as well.
  • Collection<XmlElement> parameters. This represents parameters of the token to be issued, e.g. required and optional claims, token type etc. It seems to be that this parameter is supposed to receive child elements of the WS-TrustRequestSecurityToken element. At least, <wst:Claims Dialect="…">…</wst:Claims> works as expected for both required and optional claims.
  • Uri privacyNoticeLink, int privacyNoticeVersion. The URI specify where the privacy notes are located and the version notifies the card selector weather the privacy notes were updated since last time. Both can be null, but only together at once.
  • bool isManagedIssuer. Despite of the name this has nothing to do with whether or not the card is self-issued or managed one. The unmanaged API documentation says: “Determines whether a managed presentation is to be used. This should be set to true if the service represented by this POLICY_ELEMENT has made the RequireFederatedIdentityProvisioning policy assertion.” So, in the simplest case, it is supposed to be ‘false’.

When the policy element is ready, it can be wrapped into an array and passed to the GetToken method along with the token serializer. A System.IdentityModel.Tokens.GenericXmlSecurityToken object is returned as a result of the method call. GenericXmlSecurityToken has a TokenXml property of type XmlElement containing the encrypted security token to be passed to the RP.

Next time I hope to post some source code demonstrating this approach. Stay tuned!

Useful links:


Written by Sergey Shishkin

20.02.2007 at 15:46

Posted in Uncategorized