Insights

Enrich Your Claims When Customizing ASP.NET Identity User

September 24, 2018

ASP.NET Identity is a powerful replacement for the older (and weaker) membership system Episerver uses out-of-the-box.

One of the largest weaknesses with the old identity management framework, like Membership, was that it was too cumbersome to customize the storage. With the introduction of ASP.NET Identity a few years back, they’ve achieved a clear separation of the storage of the identity information (e.g. username, password, etc.) from the code that implements the security (e.g., password hashing, password validation, etc.).
This is achieved by placing all the account related data behind an interface, IUser, and the storage operations behind another interface, IUserStore. If we are to customize the definition of a user, like adding a new personal characteristic, we simply create a custom implementation of IUser and use it as part of your Startup (not covered with this blog-post).

public class CustomerIdentityUser : IdentityUser, IUIUser 
{
  /// <summary>
  /// Access rights
  /// </summary>
  public CustomerIdentityUserAccessRight? AccessRight { get; set; }

}

[Flags]
public enum CustomerIdentityUserAccessRight
{
    ReadOnly = 1, //Can only read
    Modify = 2, //Can modify
    Manage = 4 //Can manage 

    /*
     *  0000001 = 1
     *  0000010 = 2
     *  0000100 = 4
     *  0001000 = 8
     *  0010000 = 16
     *  0100000 = 32
     *  1000000 = 64
     */ 
}

Above introduces a new characteristic called AccessRight, which describes the do’s and don’ts for a given user. Relying on this information throughout our application, like in Episerver’s VirtualRoles, requires us to enrich the ClaimsIdentity with this new piece of information.

public class CustomizedClaimsIdentityFactory : ClaimsIdentityFactory<CustomerIdentityUser>
{   
    public override async Task<ClaimsIdentity> CreateAsync(UserManager<CustomerIdentityUser, string> manager, CustomerIdentityUser user,
        string authenticationType)
    {
        if (user == null)
            return null; //If there's no user, we can't generate an identity

        ClaimsIdentity identity = await base.CreateAsync(manager, user, authenticationType);

        if ((user.AccessRight & CustomerIdentityUserAccessRight.ReadOnly) == CustomerIdentityUserAccessRight.ReadOnly)
            identity.AddClaim(new Claim(ClaimTypes.AccessRightClaimType, "readonly"));

        if ((user.AccessRight & CustomerIdentityUserAccessRight.Modify) == CustomerIdentityUserAccessRight.Modify)
            identity.AddClaim(new Claim(ClaimTypes.AccessRightClaimType, "modify"));

        if ((user.AccessRight & CustomerIdentityUserAccessRight.Manage) == CustomerIdentityUserAccessRight.Manage)
            identity.AddClaim(new Claim(ClaimTypes.AccessRightClaimType, "manage"));

        return await Task.FromResult(identity);
    }
}

It somewhat speaks for itself! In order to register the new enrichment mechanism, you need to overwrite the ClaimsIdentityFactory property during the initialization of your UserManager.

manager.ClaimsIdentityFactory = new CustomizedClaimsIdentityFactory();

When you’re looking to leverage the new claims you’ve added, simply access the ClaimsIdentity and use the HasClaims method – here’s an example relying on Episerver’s VirtualRoles.

class IsAuthenticatedAsManagerAccess : VirtualRoleProviderBase
{
    public override bool IsInVirtualRole(IPrincipal principal, object context)
    {
        if (principal.Identity == null)
            return false;

        if (principal.Identity is ClaimsIdentity)
        {
            ClaimsIdentity claimsIdentity = principal.Identity as ClaimsIdentity;

            //If user has a manager access right claim
            if (claimsIdentity.HasClaim(c => c.Type.Equals(ClaimTypes.AccessRightClaimType) && c.Value.Equals("manage")))
                return true;
        }

        return false;
    }
}

Happy Coding!
 

Meet The Challenges Of Today's Digital Economy

Ready to take that first step and rise to your digital potential? Contact Valtech today.
Talk to Us