This is part two of a Multi Blog post on "writing your own Trusted Identity provider / Claim Provider for SP2010".
In the first post I covered:

In this post I will cover:

Create a Custom SPClaimProvider

For SharePoint 2010 to Trust any Identity Provider, we need a SPClaimProvider specific for that provider. This SPClaimProvider has two main purposes:

  • Provide a way for SharePoint to communicate with any Trusted Identity Provider in a uniform (Interface) way.
  • And provide SharePoint a way to use the same Claims for Users that have logged in through a different (e.g. AD) Identity Provider, let's call this Claims Augmentation

To create a SPClaimProvider follow the following steps:

  • Create a new VS2010 Empty SP2010 Project
  • And add references to Microsoft.IdentityModel, Microsoft.SharePoint and Microsoft.SharePoint.Security.
  • Create a new Class, let's name it CustomClaimsProvider and inherit from:Microsoft.SharePoint.Administration.Claims.SPClaimProvider
  • Implement all the methods for resolving claims, this is so we can use the claims provided within SharePoint to give rights to claims:
    • FillHierarchy
    • FillResolve
    • FillSearch, FillSchema
    • FillClaimTypes,FillClaimValueTypes,FillEntityTypes
  • Implement FillClaimsForEntity for the claims augmentation
  • Override the SupportsEntityInformation,SupportsHierarchy,,SupportsResolve and SupportsSearch properties and let them "return True" since we have implemented all the Fill Methods for this SPClaimProvider
  • Give your Provider a Name by overriding the Property Name. You will need this later on.

In fairness, this post has an excellent description on the subject also.
Sample implementation of FillClaimsForEntity

 1: /// <summary>
 2: /// Get's the username part of a claims authentication login claim 
 3: /// figure out who the user is so we know what team to add to their claim
 4: /// the entity.Value from the input parameter contains the name of the 
 5: /// authenticated user. for a SQL FBA user, it looks something like
 6: /// 0#.f|sqlmembership|user1; for a Windows claims user it looks something
 7: /// 0#.w|steve\\wilmaf
 8: /// 0#.t|Customsleden|stef@tamtam.nl
 9: /// </summary>
 10: /// <param name="identityClaims"></param>
 11: /// <returns>only the login part</returns>
 12: public static string GetLoginPartFromIdentityClaim(string identityClaims) {
 13:     string login = identityClaims;
 14:     if (!string.IsNullOrEmpty(login) && login.Contains("|")) {
 15:         string[] parts = login.Split('|');
 16:         if (parts.GetLength(0) == 3) // formsbased or trusted provider based
 17:             login = parts[2];
 18:         if (parts.GetLength(0) == 2) // windows based
 19:             login = parts[1];
 20:     }
 21:     return login;
 22: }
 23:  
 24: /// <summary>
 25: /// Add Claims to a logged in User, from Dynamics CRM info
 26: /// </summary>
 27: /// <param name="context">Current Context, url</param>
 28: /// <param name="entity">the logged in user/claim</param>
 29: /// <param name="claims">The list of claims for the user</param>
 30: protected override void FillClaimsForEntity(Uri context, SPClaim entity, List<SPClaim> claims) {
 31:     if (claims == null)
 32:         throw new ArgumentNullException("claims");
 33:     if (entity == null)
 34:         throw new ArgumentNullException("entity");
 35:  
 36:     Logging.LogMessage(entity.Value);
 37:  
 38:     string login = Utilities.GetLoginPartFromIdentityClaim(entity.Value);
 39:  
 40:     // if windows user, get the email ?
 41:     if (!string.IsNullOrEmpty(login)) {
 42:         Logging.LogMessage(string.Format("User is {0}", login));
 43:  
 44:         CRMClient.Entities.User user = null;
 45:         string email = login;
 46:         if (login.Contains("@")) {
 47:             user = CRMClient.CrmSQLClient.GetUserByEmail(login);
 48:         }
 49:         if (login.Contains("\\")) {
 50:             user = CRMClient.CrmSQLClient.GetUser(login);
 51:             if (user != null)
 52:                 email = user.Email;
 53:         }
 54:         // employee, crm users
 55:         if (user != null) {
 56:             try {
 57:                 Logging.LogMessage(string.Format("User is SystemUser of CRM with an license, Name:{0}", user.FullName));
 58:  
 59:                 claims.Add( GetClaim(CustomClaimsProvider.CustomAccountTypeClaimType, "everyone"));
 60:  
 61:                 SPClaim employee = null;
 62:                 if (user.FullLicense) { // admin and or full license                            
 63:                     employee = GetClaim(CustomClaimsProvider.CustomAccountTypeClaimType, "employee");
 64:                 }
 65:                 else {// readonly 
 66:                     employee = GetClaim(CustomClaimsProvider.CustomAccountTypeClaimType, "employeero");
 67:                 }
 68:                 if (employee != null)
 69:                     claims.Add(employee);
 70:             }
 71:             catch (Exception exc) {
 72:                 Logging.LogException(exc);
 73:             }
 74:         }
 75:         else {
 76:             Logging.LogMessage(string.Format("{0} not found as SYSTEMUSER in CRM", login));
 77:         }
 78:     }
 79: }

Register your Claims Provider for SharePoint

In order for your Claims Provider to be registered within SharePoint 2010 you will need to create a specific type of Feature.

  • Add a Farm Feature to your Project
  • Add an EventReicever to your new Feature
  • And let your receiver inherit from SPClaimProviderFeatureReceiver (see: Register)
  • And now implement the following Properties in your Feature Event Receiver
    • ClaimProviderDisplayName
    • ClaimProviderDescription
    • ClaimProviderAssembly
    • ClaimProviderType

You can use this to return the last two properties:

 1: /// <summary>Get the Full Assembly Name of the Claim provider we want to register</summary>
 2: public override string ClaimProviderAssembly {
 3:     get {
 4:         return typeof(CustomClaimsProvider).Assembly.FullName;
 5:     }
 6: }
 7:  
 8: /// <summary>Get the Class Type of the Claim provider we want to register</summary>
 9: public override string ClaimProviderType {
 10:     get {
 11:         return typeof(CustomClaimsProvider).FullName;
 12:     }
 13: }

That's it, you can now register your Claims Provider, and if you want you can use this as is.
Next post will be on these subjects:

  • Create a Trust between your Tusted Identity Provider (STS) and SharePoint 2010
  • Create or Configure your SP2010 WebApplication to use the Tusted Identity Provider