MSDN Magazine - October 2008 - (Page 71) a problem when it comes to serialization, and if that is a concern, you should probably stick to primitive types. The purpose of the Right property will become clearer once we talk about claim sets. You can create a new claim by either using the Claim constructor or taking advantage of one of the static methods on the Claim class (for standard claim types): Claim purchaseLimitClaim = new Claim( 'http://www.leastprivilege.com/claims/purchaselimit', 5000, Rights.PossessProperty); Claim nameClaim = Claim.CreateNameClaim('Alice'); Figure 5 Finding Claims and Claim Sets public void ShowAuthorizationContext() { AuthorizationContext context = ServiceSecurityContext.Current.AuthorizationContext; foreach (ClaimSet set in context.ClaimSets) { Console.WriteLine(‘\nIssuer:\n’); Console.WriteLine(set.Issuer.GetType().Name); foreach (Claim claim in set.Issuer) { ShowClaim(claim); } Console.WriteLine(‘\nIssued:\n’); Console.WriteLine(set.GetType().Name); foreach (Claim claim in set) { ShowClaim(claim); } Claim Sets A claim usually doesn’t arrive by itself. Claims are typically grouped in claim sets. The class ClaimSet holds a list of claims as well as a reference to the issuer of those claims: [DataContract(Namespace='http://schemas.xmlsoap.org/ws/2005/05/identity')] public abstract class ClaimSet : IEnumerable , IEnumerable { public abstract ClaimSet Issuer { get; } public abstract Claim this[int index] { get; } public static ClaimSet System { get; } public static ClaimSet Windows { get; } } } } private void ShowClaim(Claim claim) { Console.WriteLine(‘{0}\n{1}\n{2}\n’, claim.ClaimType, claim.Resource, claim.Right); } The issuer is an important concept once your distributed system gets more complex. Claims could come from various sources such as the current service, the calling service, or a security token service. Having an issuer associated with the set allows the service to distinguish between claim sources (which may also influence trust decisions). An issuer is also described as a claim set, and System.IdentityModel ships with two predefined issuer claim sets called System (for claims coming from the system) and Windows (for claims coming from the Windows security subsystem). Both are available as static properties on the ClaimSet class. Another important concept is the claim set’s identity. A claim set typically needs a single claim that uniquely identifies the subject it describes. This is where the Right property on the Claim class comes into play. A claim set should have a single claim that has a Right value of Identity (this is the unique identifier) and a number of claims with a Right value of PossessProperty (additional claims describing the subject). You can create your own claim sets by creating a DefaultClaimSet instance or, when you need more control, by deriving from the abstract class ClaimSet: DefaultClaimSet myClaimSet = new DefaultClaimSet(ClaimSet.System, new List { new Claim(ClaimTypes.Name, 'Alice', Rights.Identity), new Claim(purchaseLimitClaimType, 5000, Rights.PossessProperty), Claim.CreateMailAddressClaim(new MailAddress('alice@leastprivilege.com')) }); Due to the general-purpose nature of claim sets, you will typically end up writing your own domain-specific extensions that work against the claim set data structure. Extension methods in C# 3.0 are a convenient way to extend these types with custom functionality. (I have written a library of extension methods for Claim, ClaimSet, and related types that you can download from leastprivilege.com/IdentityModel.) AuthorizationContext System.IdentityModel ships with two claim sets for converting Windows tokens and X.509 certificates to claims—these are WindowsClaimSet and X509CertificateClaimSet, respectively. These two claim sets are used by WCF for the Windows and Certificate client credential types. ClaimSet provides two processing primitives for querying the claims: FindClaims and ContainsClaim. FindClaims returns a collection of claims for the specified claim type, whereas ContainsClaim gives you information about the existence of a specific claim. msdnmagazine.com The last missing piece in the IdentityModel puzzle that you need to know before doing some real work with claims is the authorization context, which acts as a container for claim sets as well as transformation policies (more on this later). WCF makes the authorization context available via the thread-static ServiceSecurityContext. You can use the code snippet shown in Figure 5 to dump the claim sets and claims that are associated with the current service operation request. When you place this code into a WCF service, you will see different output depending on the configured client credential type. If Windows authentication is enabled, the WCF-generated claim set will contain the user’s SID (identity claim), the group’s SIDs, and the user name. For a request that is authenticated using a client certificate, the claim set will contain claims that describe the subject name, public key, thumbprint (identity claim), expiration dates, and so on. For users that authenticate with a simple user name/password pair, there will be only a single user name identity claim. So you can see that the WCF integrated claims layer converts technology-specific identity information, such as a Windows token or certificate, to a general-purpose data structure that can be queried using standard APIs. This makes writing services that have to support multiple credential types much easier—you are not hardwired to any technology-specific APIs anymore. If new credential types are added to WCF, the corresponding plumbing will take care of converting that proprietary format to claims as well. October 2008 71 http://www.leastprivilege.com/IdentityModel http://www.leastprivilege.com/IdentityModel http://www.msdnmagazine.com
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.