Complex Claim Values with WIF

October 28, 2012

The Windows Identity Foundation Claim class has a property named Value which is of type String. This being a string can be somewhat restrictive. There are clearly defined reasons for this limitation:

In order to reduce dependencies and simplify administration, in WIF the value of a claim is represented only as a string. For more complicated value types, it is recommended that you use standard XML schema types to serialize the value into a string. – msdn

In addition to this, claims must be serializable in order that it be persisted to the FedAuth cookies by WIF.

However, there are occasions where it is difficult to encapsulate a value in a simple string. Consider attempting to store an individuals passport details in the ClaimCollection of the users ClaimsIdentity: this doesn’t happen easily out of the box. One approach could be to store each of the values of interest individually in its own claim, however it is unlikely that the values have much, if any, meaning individually. Another approach may be to create a Passport object which could be stored on the server with only a key reference to the object being passed in the FedAuth cookies. There are potential drawbacks with this approach also, for example numerous round trips to a data store on each HttpRequest or potential issues in server farms with memory storage mechanisms;

Ideally we would be able to extend WIF’s capabilities to handle more complex objects, therefore encapsulating all of the concepts (Passport) data in a single object, and leveraging the full advantages of stateless transactions. This post presents an approach to extending the WIF Claim object to handle more complex scenarios.

Approach

Json serialization will be used to convert objects implementing ClaimValue (in this example taking the Passport claim previously outlined) into their corresponding string representation for storage in a claim. Working with ClaimValue objects will be simplified by the creation of ComplexClaim<T>: an extension of WIF’s Claim class allowing continued use of the WIF infrastructure whilst enabling complex claim type functionality.

Access and manipulation of ClaimValue values once added to the users ClaimCollection will be done through extension methods on the ClaimsIdentity object.

N.B. that this post details the concept, and I therefore haven’t gone into any detail regarding customizing the serialization/deserialization process.

Code

ClaimValue Abstract Class

The principle behind this approach is very simple: all classes which act as complex claims should implement the ClaimValue abstract class. In merit of this the ToString() method is overriden to return a Json representation of the implementing class. Also the implementing class is forced to provide a ClaimValueType string value which may assist in processing of the value at a later stage.

Source code: ClaimValue abstract class

using Newtonsoft.Json;

public abstract class ClaimValue {
    public abstract string ValueType();

    public override string ToString()
    {
        return JsonConvert.SerializeObject(this);
    }
}

 

UKPassport ClaimValue Class

For the example outlined in the introduction (i.e. storing users passport details as a claim) we need to provide a POCO which implements ClaimsValue and encapsulates all of the key attributes which are important about the passport. It may have been nice to represent this object as a struct given the value types it encapsulates, but that would mean that we wouldn’t have been able to use the abstract base class (structs can only implement interfaces).

Also worth noting here is the nested static classes used to provide string constants in the ValueType() method. This way of storing string values is borrowed from Dominick Baier’s open source STS, built on WIF, IdentityServer. I find this a very convenient way to group together constant values related to claims. I have chosen this over a resx file, as this allows the values to be passed into attribute constructors more easily if adopting an action/resource authorization infrastructure.

Source code: UKPassport ClaimValue class

using System;

public class UKPassport : ClaimValue {
    public const string Name = "UKPassport";

    private readonly PassportCode code;
    private readonly int number;
    private readonly DateTime expiryDate;

    public UKPassport(PassportCode code, int number, DateTime expiryDate)
    {
        this.code = code;
        this.number = number;
        this.expiryDate = expiryDate;
    }

    public PassportCode Code { get { return this.code; } }
    public int Number { get { return this.number; } }
    public DateTime ExpiryDate { get { return this.expiryDate; } }

    public override string ValueType()
    {
        return ClaimConstants.ClaimValueTypes.Passport;
    }
}

 

Passport Code Enum

A simple enum for the various UK passport codes.

Source code: PassportCode enum

public enum PassportCode {
    GBR,

    GBD,

    GBO,

    GBS,

    GBP,

    GBN
}

 

Generic ComplexClaim Class

The chaining of the constructors in ComplexClaim<T> sets up the .Net provided Claim without losing any functionality/constructor options. Ultimately the Json serialized ClaimValue is stored in the base Claim object. However, it is overriding the Value property and using the new keyword which allows us to customize the return value type to correspond with with the generic type specified at construction.

Source code: ComplexClaim<T> class

using Microsoft.IdentityModel.Claims;
using Newtonsoft.Json;

public class ComplexClaim<T> : Claim where T : ClaimValue {
    public ComplexClaim(string claimType, T claimValue)
        : this(claimType, claimValue, string.Empty)
    {
    }

    public ComplexClaim(string claimType, T claimValue, string issuer)
        : this(claimType, claimValue, issuer, string.Empty)
    {
    }

    public ComplexClaim(string claimType, T claimValue, string issuer, string originalIssuer)
        : base(claimType, claimValue.ToString(), claimValue.ValueType(), issuer, originalIssuer)
    {
    }

    public new T Value
    {
        get {
            return JsonConvert.DeserializeObject<T>(base.Value);
        }
    }
}

 

Simplifying Working With ComplexClaim<T> With Extension Methods on ClaimsIdentity

Extension methods provide an easy way to extend the behaviour of the ClaimsIdentity class and customize its functionality to suit with the application.

Source code: ClaimsIdentity extension methods

using System;
using System.Linq;
using Microsoft.IdentityModel.Claims;

public static class ClaimsIdentityExtensions {
    public static void AddPassport(this ClaimsIdentity identity, UKPassport passport)
    {
        var complexClaim = new ComplexClaim<UKPassport>(ClaimConstants.ComplexClaimTypes.CurrentPassport, passport);
        identity.Claims.Add(complexClaim);
    }

    public static bool IsCurrentPassportExpired(this ClaimsIdentity identity)
    {
        var passport = GetPassport(identity, ClaimConstants.ComplexClaimTypes.CurrentPassport);
        return DateTime.Now > passport.ExpiryDate;
    }

    public static bool IsBritishCitizen(this ClaimsIdentity identity)
    {
        var passport = GetPassport(identity, ClaimConstants.ComplexClaimTypes.CurrentPassport);
        return passport.Code == PassportCode.GBR;
    }

    private static UKPassport GetPassport(this ClaimsIdentity identity, string passportType)
    {
        var passportClaim = identity.Claims.Single(claim => claim.ClaimType == passportType) as ComplexClaim<UKPassport>;
        return passportClaim.Value;
    }
}

 

Example Usage

Code implementing the complex claim values now becomes very easy to manage. The example below demonstrates creating a Passport claim value, adding it to the ClaimsIdentity via the AddPassport() extension method, then using further extension methods to access the data as required.

Source code: Implementation of the approach

using System;
using Microsoft.IdentityModel.Claims;

class Program {
    private static ClaimsIdentity identity = new ClaimsIdentity();

    static void Main(string[] args)
    {
        var oldPassport = CreatePassport();
        identity.AddPassport(oldPassport);

        var britishCitizen = identity.IsBritishCitizen();
        var hasExpired = identity.IsCurrentPassportExpired();
    }

    private static UKPassport CreatePassport()
    {
        var passport = new UKPassport(
            code: PassportCode.GBR, 
            number: 123456789,
            expiryDate: DateTime.Now);

        return passport;
    }
}

 

Summary

This post has highlights a limitation of WIF’s Claim class when dealing with complex data: notable that it only allows string keys and values, or standard xml schema types. It has also highlighted the reasons behind the string value limitation of the class.

Two options for working around this limitation were considered: storing related values individually in their own claim and storing a complex object encapsulating the values in a server side data store and passing a key identifier in the FedAuth cookies.

The approach continues by outlining an approach for extending the WIF framework to handle complex objects through ComplexClaim<T> and ClaimValue objects.

Hope that this is useful! Happy coding :-)

Please note: the opinions expressed in this blog are my own and don't necessarily represent those of Aridhia Informatics.

tags: , ,
posted in Authentication by admin

Follow comments via the RSS Feed | Leave a comment | Trackback URL

2 Comments to "Complex Claim Values with WIF"

  1. Richard wrote:

    Hi, as published this does not work with VS2012 and .Net 4.5 WIF (using System.Security.Claims). The call to GetPassport returns null. Any update to your otherwise excellent article would be most welcome.

  2. Systempuntoout wrote:

    Nice article! Indeed, with .Net 4.5 the call to GetPassport returns null.
    Any hints?

Leave Your Comment