ADFS SharePoint attribute store

Hi guys, it’s Paweł again – your SharePoint architect trying to make own little name in the identity world. In one of my previous posting from SharePoint meets identity series, I was writing about ADFS and its features. One of them was the ability to perform various operation on claims using attribute stores. During the course of the project which inspired this series, I had an challenging opportunity to create a custom attribute store which would provide data from SharePoint lists. So I thought it would be great if I shared my great invention with the outside world and the outside world should appreciate it as well, so this post will be all about that.

The full story behind the need for SharePoint attribute store is that we have a setup of Internet-facing SharePoint 2010 which uses ADFS+ACS (Azure Access Control Service) as an authentication proxy. All of the users of this portal will be coming from the outside world – not registered in the “home” AD. Using ACS allows us to externalize authentication process but still we have to handle authorization. Because all users information we store in SharePoint itself and it would be redundant to create some SQL or LDAP database just for handling claims, I decided to get users information directly from SharePoint at ADFS level, so that ADFS can perform claims authorization logic based on this information.

How to use it

ADFS attribute stores can be used during claims pipeline processing and are invoked from claim rule language, where a specific query to the particular store is executed. Knowing SharePoint a bit, you might have heard about CAML, which is XML-based language and one of its purposes is performing queries to SharePoint lists – so it will serve attribute store purpose to provide information which can be used to issue claims.

So let’s look at this by example. This is a somewhat typical CAML query:

[sourcecode language=”xml”]
<View>
<Query>
<Where>
<Or>
<Eq>
<FieldRef Name=’Email’/>
<Value Type=’Text’>pawel.szczecki@predica.pl</Value>
</Eq>
<Eq>
<FieldRef Name=’ExternalId’/>
<Value Type=’Text’>PSZ005</Value>
</Eq>
</Or>
</Where>
</Query>
<ViewFields>
<FieldRef Name=’Title’/>
</ViewFields>
</View>
[/sourcecode]

I think most of it (at least Query part) is pretty self-explanatory – we are looking for a person (me!) by e-mail or ID. But what’s important to note from the attribute store point of view is that ViewFields part has to be included in the query as it indicates which columns from the SharePoint list will be returned in the result set and thus can be used as claim values. So this query should return last name (contained in Title field) if e-mail or ID match. The resulting claim rule would be:

[sourcecode language=”false”]
ce:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]
&& cn:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"]
=> issue(store = "SharePoint Site",
types = ("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"),
query = "<View><Query><Where><Or><Eq><FieldRef Name=’Email’/><Value Type=’Text’>{0}</Value></Eq><Eq><FieldRef Name=’ExternalId’/><Value Type=’Text’>{1}</Value></Eq></Or></Where></Query><ViewFields><FieldRef Name=’Title’/></ViewFields></View>",
param = ce.Value, param = cn.Value);
[/sourcecode]

As simple as that 😉 Of course it’s important to note that ADFS service account must have permissions to connect to SharePoint and query the list to get the data which also means that SharePoint web application hosting the data must have Windows Authentication turned on. The site URL and the list name are configured values therefore they are not present here.

How to install and configure it

All the stuff you need to start playing around with it is under:

CodePlex: Project site, Download

GitHub: Project site, Download

The resulting DLL must be copied to ADFS directory (C:Program FilesActive Directory Federation Services 2.0) or to Global Assembly Cache. I tested using the latter, so let me know if something’s wrong if you use the other approach.

Simple PowerShell script is provided with the binary and source which does ADFS configuration – it only needs modification in terms of SharePoint site URL and list name to match yours.
Alternatively, the custom attribute store can be added in ADFS console directly, then configuration values which need to be put there are:

Display Name: whatever_you_wish
Class Name: Predica.Tools.SharePoint.SharePointAttributeStore.SharePointListAttributeStore, Predica.Tools.SharePoint.SharePointAttributeStore, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8e7c7c1f18b74e88
Parameters:

SiteUrl: your_SharePoint_site_URL
ListName: name_of_the_list_with_claims_data

Of course writing a custom attribute store is no rocket science at all, you can do it yourself with this nice MSDN article, nevertheless I think it’s always better to have something done for you, so I hope this piece of code will be of any use to someone.

Image courtesy of Stuart Miles / FreeDigitalPhotos.net

Category: Development

Leave a Reply