Writing your own Trusted Identity provider for SP2010 (2)
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:
- Create a Custom Security Token Service with the Windows Identity Framework SDK
In this post I will cover:
- Create a Custom SPClaimProvider
- Register your Custom SPClaimProvider
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