Wednesday 15 September 2010

Shibboleth IdP – Getting the eduPersonScopedAffiliation attribute from Active Directory using security groups

I have implemented a Shibboleth IdP which authenticates users against our Server 2008 R2 forest and domain functional level Active Directory
We are a member of the UK Access Management Federation for Education and Research, which require the following attributes to be available:
eduPersonScopedAffiliation:                      user's organisational affiliation
eduPersonTargetedID:                                persistent user pseudonym for personalisation
eduPersonPrincipalName:                           persistent user id across multiple services
eduPersonEntitlement:                               extensible list of URIs for extra properties
Using the attribute-resolver.xml file, eduPersonPrincipalName is linked to the sAMAccountName attribute in our directory service, and the eduPersonEntitlement is linked to an extension attribute in the directory. eduPersonTargetedID is a computed value using the objectGUID  attribute in our directory and encrypted using a salt.
eduPersonScopedAffiliation is an interesting one. Originally we had planned to link it to another extension attribute in the directory, and reconfigure our management tool to add the staff or student value as well as the member value to the attribute. This worked as long as there was only one entry specified in the extension attribute, as soon as we tried any number of different combinations of staff and member for example, the attribute wasn’t released.
After extensive research and trying different methods I came up with, I contacted the UK federation service desk. They are really great guys and worked relentlessly to find a solution to our problem. Specifically Sara and Steve (thanks to the both of you!)
We found a script (link below) which will generate the eduPersonScopedAffiliation based on OU. This in most cases would be ideal (specify the students OU and the staff OU) unfortunately our directory structure doesn’t separate staff and students by OU (not my design!) therefore this would not work.
Never the less here is the link
What we do have, is a security group for staff, and a security group for students. Steve decided he would use the script as a template and modify it to look at groups instead. Steve made a good start and handed over to Sara when he went on vacation.
We were having problems getting the script to see the group membership, we come across this document which detailed how someone else had setup the eduPersonScopedAffiliation, although it wasn’t what we needed,  it turned out their syntax was pretty useful and Sara go the script working!
This script looks for group membership that CONTAINS the specified words. Therefore your security groups only need to contain the words you specify.
The users need to be an explicit member of the group, unfortunately it doesn’t work for nested groups, however the script is pretty simple to expand by copying and pasting, so If you had two groups you wanted to use,  instead of nesting them into one main group, just specify them both in the script.
The first step is to uncomment the eduPersonAffiliation attribute, this will be used as a source attribute for the eduPersonScopedAfailiation attribute and is where the script magic happens. It should be as follows:
 <resolver:AttributeDefinition xsi:type="Script" xmlns="urn:mace:shibboleth:2.0:resolver:ad"
                              id="eduPersonAffiliation">
    <!-- Dependency that provides the source attribute. -->
    <resolver:Dependency ref="myLDAP" />
    <!-- SAML 1 and 2 encoders for the attribute. -->
    <resolver:AttributeEncoder xsi:type="SAML1String" xmlns="urn:mace:shibboleth:2.0:attribute:encoder"
                 name="urn:mace:dir:attribute-def:eduPersonAffiliation" />
    <resolver:AttributeEncoder xsi:type="SAML2String" xmlns="urn:mace:shibboleth:2.0:attribute:encoder"
                 name="urn:oid:1.3.6.1.4.1.5923.1.1.1.1"
                               friendlyName="eduPersonAffiliation" />
    <!-- The script, wrapped in a CDATA section so that special XML characters don't need to be removed -->
    <Script><![CDATA[
        importPackage(Packages.edu.internet2.middleware.shibboleth.common.attribute.provider);
        eduPersonAffiliation = new BasicAttribute("eduPersonAffiliation");
        // If the user has group membership
        if (typeof memberOf != "undefined" && memberOf != null ){
            for (i=0; memberOf != null && i < memberOf.getValues().size(); i++) {
                value = memberOf.getValues().get(i).toLowerCase();
                if (value.contains("teachers")) {
                    eduPersonAffiliation.getValues().add("staff");
                    eduPersonAffiliation.getValues().add("member");
                }
                if (value.contains("students")) {
                    eduPersonAffiliation.getValues().add("student");
                    eduPersonAffiliation.getValues().add("member");
                }
            }
        }
    ]]></Script>
</resolver:AttributeDefinition>
You then need to configure eduPersonScopedAffiliation to use eduPersonAffiliation as its source (uncomment it if need be)
<resolver:AttributeDefinition id="eduPersonScopedAffiliation"
  xsi:type="Scoped" xmlns="urn:mace:shibboleth:2.0:resolver:ad"
  scope="yourdomain.com" sourceAttributeID="eduPersonAffiliation">
    <resolver:Dependency ref="eduPersonAffiliation" />
    <resolver:AttributeEncoder xsi:type="SAML1ScopedString"
      xmlns="urn:mace:shibboleth:2.0:attribute:encoder"
      name="urn:mace:dir:attribute-def:eduPersonScopedAffiliation" />
    <resolver:AttributeEncoder xsi:type="SAML2ScopedString"
      xmlns="urn:mace:shibboleth:2.0:attribute:encoder"
      name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9"
      friendlyName="eduPersonScopedAffiliation" />
</resolver:AttributeDefinition>
We then used the UK Federation test SP’s session dumper to see what had been released.

3 comments:

  1. Thanks for this post. I have bang my head against the wall for a couple of days trying to get the eduPersonScopedAffiliation to work a service provider.

    GEM

    ReplyDelete
  2. Good shit! I had the first part working based on the Shibbolet wiki but was lacking the configuration that set eduPersonScopedAffiliation to use eduPersonAffiliation. Nice work!

    ReplyDelete
  3. The installation of shibboleth idp will be configured through an process for XML and with API.This API will helpful for an Active Directory and will be scoped to the local directories only.

    Regards Mike

    ReplyDelete