Microsoft SharePoint 2010, with its built-in support for retrieving trusted attributes about a user upon login (or what is commonly referred to as claims), can be used to authenticate users and authorize access to content. As I’ve written about previously, this allows businesses to implement new and interesting information protection policies. SharePoint also allows us to build and deploy custom claim providers that can retrieve attributes from a wide variety of sources and transform them in order to enforce specific policies within SharePoint. This article will walk through a simple example of building a custom claim provider and review some of the technical considerations that need to be taken into account.
A few weeks ago I gave a talk the Federal SharePoint User Group in Washington DC. Really good group there! Thanks to the 40 people or so that dialed into web cast for it. I`ve been traveling a lot the last few weeks with RSA 2012 and other shows, but I`ve finally gotten a chance to put the sample claim provider code I used in the presentation on our blog. Its a simple example and the process of building a claim provider is not too hard, but it is worth walking through the steps.
First I need to thank the excellent articles on Steve Peschka’s blog for the background and detailed information about developing for SharePoint using claims and federated identities. I highly recommend you check them out. The example here is based on some of those examples, but I’ve built this code with a different use case in mind and some additional detail in some of the steps in order to assist those developing custom claim providers for the first time.
Where do Custom Claim Providers Fit
In order to see how a custom claim provider fits into a SharePoint architecture that uses claims based authentication, you can refer to a previous article I`ve posted: An Architecture for Claims Based Authorization in SharePoint.
At a high level, here is what this could look like:
The Scenario – Setting It Up
In the Intelligence, Military and Government community, our customers tell us that managing an user’s security clearance is no trivial task. Users can have a wide variety of security clearances, and often there is a hierarchy associated with them. For example, if a user has Secret clearance, that typically permits them to access content that is classified as Secret and Confidential (with Confidential being the lower security clearance), but not Top Secret. If a user has Top Secret clearance, then they’re permitted to access content classified as Top Secret, Clearance and Confidential. Within a user’s identity however, customers often do not want to store multiple security clearances for them – they typically just want to store the user’s highest level of clearance, and have logic for determining all the content classifications they’re permitted to access executed somewhere else. This is the scenario that our example will follow.
A user will login to SharePoint and we’ll assume that a single security clearance (their highest level) is retrieved from an external trusted provider like ADFS 2.0. Our custom claim provider will then examine the clearance level returned and execute some simple logic to add any additional security clearances the user is entitled to.
Step by Step – Building a Custom Claim Provider for Security Clearance
1. Create a New Project
We start building a Custom Claim Provider by creating a new SharePoint 2010 project in Visual Studio 2010 (or later) and selecting an Empty SharePoint Project. Remember a custom claim provider will only be invoked in a web application that is configured for Claims Based Authentication, and Claims Based Authentication is only supported in SharePoint 2010 or later. Be sure to give your project a meaningful name, like ClaimProviderSecurityClearance.
2. Add the necessary References, Start a Class and Add Using Statements
You will need to add references to Microsoft.SharePoint (which will likely already be there) and Microsoft.IdentityModel. To do this, right click on References in the Solution Explorer pane, select Add References and selected the DLLs listed here. For the IdentityModel reference, you’ll need to browse to find it here:
\Program Files\Reference Assemblies\Microsoft\Windows Identity Foundation\v3.5\Microsoft.IdentityModel.dll.
Add a new class by right clicking on the project name in the Solution Explorer, selecting Add, then Class… In the Add New Item window, select C# Class and give it a meaningful name. A .cs file will appear in the main editing window, which will have some basic Using statements, and a skeleton class with a namespace that matches your project name.
Add the following Using statements to the ones already provided:
- using Microsoft.SharePoint;
- using Microsoft.SharePoint.Administration;
- using Microsoft.SharePoint.Administration.Claims;
- using Microsoft.SharePoint.WebControls;
3. Modify Your Class to Inherit from SPClaimProvider
You need to modify the class that you added to inherit from the base class SPClaimProvider. At this point, mine looks as follows:
4. Implement the Abstract Class
To get a skeleton implementation of the other class members, simply implement the abstract class by right clicking on base class SPClaimProvider in your .cs file and select Implement Abstract Class. This will result in a skeleton implementation of the following.
Members:
- FillClaimTypes
- FillClaimValueTypes
- FillClaimsForEntity
- FillEntityTypes
- FillHierarchy
- FillResolve(2 overrides)
- FillSchema
- FillSearch
Properties:
- Name
- SupportEntityInformation
- SupportHierarchy
- SupportResolve
- SupportSearch
As we move on, we’ll focus mainly on the implementation of the FillClaimsForEntity method and a number of helper methods.
5. Define the Properties for the Custom Claim Provider
Scroll down within your class and find where the implementation resides for the properties listed above. We need to set the appropriate properties to true depending on the behavior we want to achieve with our provider. The most important properties to consider for this example are Name and SupportsEntityInformation. The latter is important because you must set this property to true, if you are to implement the FillClaimsForEntity method and transform or augment the claims within the user’s identity. If set to false, then FillClaimsForEntity will not get called and you will not be able to manipulate the user’s claims. This section should look as follows:
The final 3 properties relate to the modifying the people picker used to select claims, users or groups in a claims based authenticated web application. Setting them to true is not strictly needed for this example, but if we want the claims defined by this provider to appear and interact appropriate with the people picker then they must be set to true and a basic implementation is required (which is shown below).
6. Create Static Properties for Name and Helper Functions
Next we need to create the following static properties in order to implement the provider’s Name, and the following helper methods to define the Claim Value and the Claim Value type:
Notice the URI used to define the claim value we’re working with (http://schemas.sample.local/clearance) which represents a security clearance. The URI can be anything you like, but it should follow a similar format for readability. The right most portion after the final / should be a meaningful name for the claim value because this is what will appear in the people picker in SharePoint. We have also defined the claim value’s type to be a string. This can be the same as a claim value that is returned from an external trusted provider like ADFS 2.0 if you wish to manipulate it after the user authenticates to ADFS 2.0. This example only defines 1 claim value, but if you were to work with multiple claim values within a provider you would replicate the following methods for each claim value you’ll be working with and give them each a unique name:
- ClearanceClaimType
- ClearanceClaimValueType
And then within the methods FillClaimTypes and FillClaimValueTypes you would have one claimTypes.Add() statement for each Claim Value you are working with.
7. Implement the Data Source and the Methods to Augment Claims
Up until this point, we were still putting in place the plumbing that is required by any custom claim provider you might build. Now we start adding our specific logic for managing security clearances in this simple case.
First we add our data source and another helper method as shown here:
Notice that for example purposes only, we’re using a simple array to define the data source and it contains only 4 possible security clearances defined simply as strings. In a real production environment, a more robust system may be used for storing and retrieving these types of attributes like MS SQL Server, an LDAP database, a PKI or Identity Management system.
The helper method shown DoesClaimValueAlreadyExist() is really useful for determining if a specific claim exists with a specific value in the user’s identity after authentication to a trusted external provider has already taken place. In this example, our external trusted provider is returning an attribute which defines the user’s highest security clearance. If the claim exists with the specified value, it simply returns a boolean. It is used heavily in the next step.
Next we’ll implement FillClaimsForEntity() where are logic for managing clearances exists. It will look as follows:
As you can see, the logic here is quite simple. Just check what their highest level of clearance is, and based on that add all the lower level clearances the user is entitled to. This logic could certainly get more complex, especially if we take things like Caveats into account or what department a user belongs to.
8. Implement People Picker Related Methods
In this example, we are not customizing the experience within the people picker so we are only including a very basic implementation here. If your business requires that the people picker be customized (because the experience is not great with claims out of the box) then you would do this by implementing a custom claims provider – look for more on that in a future post. Here is what it looks like without any customization and, although usable, it has many issues that I’ll get into in another post as well:
A minimal implementation is required in order to simply have the Clearance claim included in the people picker when it is used. The implementation would look like this:
The specific purpose of each method is as follows, related in each case specifically to the claims defined in this provider:
- FillEntityTypes – Set of possible claims to display in the people picker
- FillHierarchy – Determine hierarchy for displaying claims in the people picker
- FillResolve(2 overrides) – Logic for resolving claims specified in the people picker
- FillSchema – Specifies the schema that is used by people picker to display claims/entity data
- FillSearch – Fills in search results in people picker window
9. Define the Feature Receiver that Will Deploy the Custom Claim Provider
Custom claim providers are deployed to SharePoint 2010 as farm level features so they must be built within the context of a SharePoint feature receiver. To do this, we’ll add a new class to the project as we previously did (right click the project in the Solution Explorer, select Add, then Class and select a C# class).
The class will need to inherit from SPClaimProviderFeatureReceiver and it should look exactly as follows (with your namespace and class name):
Next we’ll need to right click on Features in the Solution Explorer and select Add Feature. You’ll see a file called Feature1.Feature. Here you must select Farm in the scope drop down and click Save. Then in the Properties pane on the right side you’ll need to set the Receiver Assembly and Receiver Class properties correctly.
This should allow the feature receiver to be deployed correctly to your SharePoint server from within Visual Studio. If you perform the deployment, then go to Central Admin and Manage Farm Features you’ll see your Custom Claim Provider listed and active by default.
Congratulations! You’ve just built and deployed your first Custom Claim Provider.
Testing Your Claim Provider
Remember, this claim provider is dependent on a few things, namely:
- One of your SharePoint 2010 web applications must be enabled for Claims Based Authentication
- A ‘clearance’ claim must be first returned from an external trusted provider like ADFS 2.0
If you are using ADFS 2.0, remember you need to first map the expected claims into SharePoint using PowerShell. If this is not done, SharePoint will simply ignore any incoming claims that have not been mapped.
If you don’t have ADFS 2.0 in place returning such a claim, you can simply add 1 more claims.Add() statement near the beginning of the FillClaimsForEntity() method that starts the user off with one of these particular claim.
Then you simply login to your SharePoint web application that is claims enabled and see which claims have been retrieved.
When you login, you’ll need a way to see what claims have been returned for that user. To help with this, we highly recommend installing the following Claim Tool for SharePoint. It will allow you to quickly view what claims SharePoint has retrieved for the user in question. I have the web part added at the site level so I see it as soon as I login and its invaluable for debugging.
Conclusion
Building custom claim providers is not difficult and, because they run as features on the SharePoint server at the farm level, they can help to implement some really interesting policies related to authenticating identities and authorization.
Once a user has signed in and their claims are retrieved, SharePoint 2010 does a great job of enforcing access control on documents/items to which claims have been assigned. Of course a user must have those claims as part of their identity to gain access to a document or item with the assigned permission level. Transforming claims in this way after they have been retrieved from ADFSv2 can allow you to implement some very robust access control policies in SharePoint. Applying those claims with permission levels to documents and items in SharePoint is still a manual and labor intensive task that can be very error prone – for more information on how the TITUS SharePoint Security Suite can automatically assign such access control policies at a fine grained level in SharePoint please read the white paper Microsoft SharePoint Security – Harness the power of claims to protect information or check out the video.
Enjoy.
-Antonio
Comments