Active Directory and other LDAP directories

For detailed configuration information please see the Shibboleth IdP v4 documentation pages:

On Linux, to configure Shibboleth to use LDAP authentication (or one of the other three password login flows) you may need to enable the password authentication module as described in the Shibboleth IdP wiki. The Windows installer does this for you automatically.

You then configure the module in the %{idp.home}/conf/ldap.properties file as described in the Shibboleth IdP wiki and the following sections.

You will also need the CA or server certificate for the LDAP server, the baseDN to search for your users, and to know whether a subtree search is required.

Configuration stages

Active Directory: authentication

If using the Windows installer then some of the configuration in ldap.properties will have been done for you already, but some values are essentially guessed, and you will need to refine it further to fit your real Active Directory configuration. In Active Directory, the variable sAMAccountName is most commonly used to hold the username of someone authenticating at the IdP, so we assume that in the following.

Going through the ldap.properties file in order we look at the properties that you may need to change; any that we do not cover here will usually not need to be changed.

 ## Authenticator strategy, either anonSearchAuthenticator, bindSearchAuthenticator, directAuthenticator, adAuthenticator
 idp.authn.LDAP.authenticator=adAuthenticator

This will normally be adAuthenticator for Active Directory; the Windows Installer with the 'Use Active Directory' box ticked sets this for you.

 idp.authn.LDAP.ldapURL=ldaps://dc0.ad.example.ac.uk:636

This is the URL of your Active Directory server. The Windows installer makes a guess at this based on the Active Directory domain name entered at installation, and it will probably need to be changed. Check whether it is ldaps or ldap, and the hostname and port number, and change as necessary.

 idp.authn.LDAP.useStartTLS                     = false
 idp.authn.LDAP.useSSL                          = true

You should use a secure protocol, either startTLS or SSL, to connect to your Active Directory domain controller using LDAP. Modify the above properties according to which protocol you will use.

 ## SSL configuration, either jvmTrust, certificateTrust, or keyStoreTrust
 idp.authn.LDAP.sslConfig                       = certificateTrust
 ## If using certificateTrust above, set to the trusted certificate's path
 idp.authn.LDAP.trustCertificates=%{idp.home}/credentials/ldap-server.crt
 ## If using keyStoreTrust above, set to the truststore path
 # idp.authn.LDAP.trustStore=%{idp.home}/credentials/ldap-server.truststore

Then configure the public key certificate of the server(s) in %{idp.home}/credentials/ldap-server.crt, or alternatively modify the above configuration to use one of the other trust methods.

The default Active Directory configuration does not have a certificate installed for StartTLS or LDAP over SSL/TLS to be enabled, so many organisations may be using unencrypted LDAP on port 389. This is insecure.

We strongly recommended you configure your Active Directory service to support either StartTLS or SSL/TLS LDAP over SSL/TLS with a Certificate, and configure your Shibboleth IdP accordingly.

 #idp.authn.LDAP.subtreeSearch                   = true
 idp.authn.LDAP.userFilter=(sAMAccountName={user})
 # bind search configuration
 # for AD: idp.authn.LDAP.bindDN=adminuser@domain.com
 idp.authn.LDAP.bindDN=ldap-search@dc0.ad.example.ac.uk

The bindDN account is configured in the idp.authn.LDAP.bindDN property in %{idp.home}/conf/ldap.properties; the password for this account is configured in the %{idp.home}/credentials/secrets.properties file. Note that the bindDN must be in the form adminuser@domain.com when using the adAuthenticator strategy. Uncomment the idp.authn.LDAP.subtreeSearch line if you need subtree searching, and check that sAMAccountName is the correct variable name to hold the authenticating individual's username; if not then change accordingly.

 idp.attribute.resolver.LDAP.searchFilter= (sAMAccountName=$resolutionContext.principal)

Again, check that sAMAccountName is the correct variable name to hold the authenticating individual's username; if not then change accordingly.

Other LDAP directories: authentication

Other LDAP directories tend to have different naming conventions from Active Directory, so a number of the variable names in the configuration will be different from those in the Active Directory examples above. They will probably use the bindSearchAuthenticator strategy and thus require the service account to be specified in a different form.

Therefore, you will need to make similar changes to ldap.properties as set out for Active Directory above, but with some differences:

 ## Authenticator strategy, either anonSearchAuthenticator, bindSearchAuthenticator, directAuthenticator, adAuthenticator
 idp.authn.LDAP.authenticator=bindSearchAuthenticator

Specify bindSearchAuthenticator for the authenticator strategy.

 # Search DN resolution, used by anonSearchAuthenticator, bindSearchAuthenticator
 # for AD: CN=Users,DC=example,DC=org
 idp.authn.LDAP.baseDN=ou=users,DC=ad,DC=example,DC=ac,DC=uk
 #idp.authn.LDAP.subtreeSearch                   = true
 idp.authn.LDAP.userFilter=(uid={user})
 # bind search configuration
 # for AD: idp.authn.LDAP.bindDN=adminuser@domain.com
 idp.authn.LDAP.bindDN=uid=ldap-search,ou=users,dc=ad,dc=example,dc=ac,dc=uk

The bindDN account is configured in the idp.authn.LDAP.bindDN property in %{idp.home}/conf/ldap.properties; the password for this account is configured in the %{idp.home}/credentials/secrets.properties file. Note that the bindDN is in a different form when using the bindSearchAuthenticator strategy from the form used with adAuthenticator. Uncomment the idp.authn.LDAP.subtreeSearch line if you need subtree searching, and check that uid is the correct variable name to hold the authenticating individual's username; if not then change accordingly.

 idp.attribute.resolver.LDAP.searchFilter= (uid=$resolutionContext.principal)

Again, check that uid is the correct variable name to hold the authenticating individual's username; if not then change accordingly.

As with Active Directory, you should always be using a secure protocol to connect to any LDAP directory service.

We strongly recommended you configure your LDAP directory service to support either StartTLS or SSL/TLS LDAP over SSL/TLS with a Certificate, and configure your Shibboleth IdP accordingly.

Active Directory and other LDAP Directories: attribute release

The IdP releases SAML attributes to SPs to provide information about the organisation and user that the IdP represents for a given authentication. Some are privacy-preserving and some are not, so your organisation needs to give consideration to which attributes are released to which SPs. For the UK federation's attribute release recommendations generally, please see section 7 of the UK federation's Technical Recommendations for Participants. There are four attributes that the UK federation regards as "core" attributes: eduPersonScopedAffiliation, eduPersonTargetedID, eduPersonPrincipalName and eduPersonEntitlement. The most commonly used of these are eduPersonScopedAffiliation and eduPersonTargetedID, so we focus on those here.

Each attribute must have a definition in the attribute-resolver.xml file, which gives instructions for generating the attribute value and format; and a filter in the attribute-filter.xml file, which gives instructions on which SPs it can be released to and under which circumstances.

The Attribute Registry service is a new addition to V4 that provides a more advanced way to configure the relationship between the internal IdPAttribute objects that are (for the most part) produced by the Attribute Resolver and the way the data is represented in the protocols supported by software like SAML, CAS, or OpenID.

For the details of this please see the Shibboleth link above; but one consequence of the introduction of the Attribute Registry service is that AttributeEncoder elements are no longer required in attribute definitions in most cases. The documentation here is intended for setting up new deployments so we provide attribute definitions here without AttributeEncoder elements. If you are migrating an older deployment we recommend you update your attribute definitions accordingly; the inclusion of AttributeEncoder elements may resulting in duplicate attribute values being released, which might result in issues with some SPs.

Attribute resolver configuration examples

Details of the Shibboleth IdP attribute resolver configuration are given in the Shibboleth attribute resolver configuration documentation. The attribute resolver configuration specifies how attributes are retrieved or generated on behalf of your users; the conf/attribute-resolver.xml file is used for this.

Some simple attribute definitions follow, with an example LDAP connector and ComputedId connector. These are based on examples in the file %{idp.home}/conf/examples/attribute-resolver-ldap.xml. Your attribute definitions will depend on which attributes are available in your LDAP.

Copy the file %{idp.home}/conf/examples/attribute-resolver-ldap.xml to %{idp.home}/conf/attribute-resolver.xml and use that as a starting point. You will need to make some changes according to your organisation's local set-up.

 <AttributeResolver
        xmlns="urn:mace:shibboleth:2.0:resolver"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver
        http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">

     <AttributeDefinition xsi:type="Scoped" id="eduPersonPrincipalName" scope="%{idp.scope}">
         <InputDataConnector ref="myLDAP" attributeNames="sAMAccountName"/>
     </AttributeDefinition>

     <AttributeDefinition xsi:type="Scoped" id="eduPersonScopedAffiliation" scope="%{idp.scope}">
         <InputDataConnector ref="myLDAP" attributeNames="eduPersonAffiliation"/>
     </AttributeDefinition>

     <AttributeDefinition xsi:type="Scoped" id="samlPairwiseID" scope="%{idp.scope}">
         <InputDataConnector ref="computed" attributeNames="computedId"/>
     </AttributeDefinition>

     <AttributeDefinition xsi:type="Scoped" id="samlSubjectID" scope="%{idp.scope}">
         <InputDataConnector ref="myLDAP" attributeNames="%{idp.persistentId.sourceAttribute}"/>
     </AttributeDefinition>

     <!-- Deprecated eduPersonTargetedID attribute -->

     <AttributeDefinition xsi:type="SAML2NameID" id="eduPersonTargetedID"
         nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">
         <InputDataConnector ref="computed" attributeNames="computedId"/>
         <AttributeEncoder xsi:type="SAML1XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10"/>
         <AttributeEncoder xsi:type="SAML2XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10"
                           friendlyName="eduPersonTargetedID"/>
     </AttributeDefinition>

     <!-- Example LDAP DataConnector based on conf/examples/attribute-resolver-ldap.xml -->

     <DataConnector id="myLDAP" xsi:type="LDAPDirectory"
         ldapURL="%{idp.attribute.resolver.LDAP.ldapURL}"
         baseDN="%{idp.attribute.resolver.LDAP.baseDN}"
         principal="%{idp.attribute.resolver.LDAP.bindDN}"
         principalCredential="%{idp.attribute.resolver.LDAP.bindDNCredential}"
         useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS:true}"
         connectTimeout="%{idp.attribute.resolver.LDAP.connectTimeout}"
         trustFile="%{idp.attribute.resolver.LDAP.trustCertificates}"
         responseTimeout="%{idp.attribute.resolver.LDAP.responseTimeout}"
         connectionStrategy="%{idp.attribute.resolver.LDAP.connectionStrategy}"
         noResultIsError="true"
         multipleResultsIsError="true"
         excludeResolutionPhases="c14n/attribute"
         exportAttributes="sAMAccountName eduPersonAffiliation">
         <FilterTemplate>
             <![CDATA[
                 %{idp.attribute.resolver.LDAP.searchFilter}
             ]]>
         </FilterTemplate>
         <ConnectionPool
             minPoolSize="%{idp.pool.LDAP.minSize:3}"
             maxPoolSize="%{idp.pool.LDAP.maxSize:10}"
             blockWaitTime="%{idp.pool.LDAP.blockWaitTime:PT3S}"
             validatePeriodically="%{idp.pool.LDAP.validatePeriodically:true}"
             validateTimerPeriod="%{idp.pool.LDAP.validatePeriod:PT5M}"
             validateDN="%{idp.pool.LDAP.validateDN:}"
             validateFilter="%{idp.pool.LDAP.validateFilter:(objectClass=*)}"
             expirationTime="%{idp.pool.LDAP.idleTime:PT10M}"/>
     </DataConnector>

     <!--
     DataConnector for pairwise-id (example depends in part on saml-nameid.properties).
     Note that this relies on BASE32 encoding in accordance with the attribute definition.
     Older uses of this plugin for legacy eduPersonTargetedID/NameID values may require
     different settings.
     -->

     <DataConnector id="computed" xsi:type="ComputedId"
             excludeResolutionPhases="c14n/attribute"
             generatedAttributeID="computedId"
             salt="%{idp.persistentId.salt}"
             algorithm="%{idp.persistentId.algorithm:SHA}"
             encoding="BASE32">
         <InputDataConnector ref="myLDAP" attributeNames="%{idp.persistentId.sourceAttribute}" />
     </DataConnector>

 </AttributeResolver>

The example above gives attribute definitions for the SAML attributes eduPersonPrincipalName eduPersonScopedAffiliation, samlPairwiseID, samlSubjectID and eduPersonTargetedID. The attribute definitions depend on the DataConnector with id="myLDAP". If your LDAP connection is secured with SSL or StartTLS then you should not need to make any changes; if it is not secured then you may need to remove or comment out the following lines from the myLDAP DataConnector:

 useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS:true}"
 trustFile="%{idp.attribute.resolver.LDAP.trustCertificates}"

We strongly recommend you configure your LDAP Server to support either StartTLS or SSL/TLS LDAP over SSL/TLS with a Certificate, and re-configure your Shibboleth IdP accordingly.

You will probably need to make changes to the following line:

 exportAttributes="sAMAccountName eduPersonAffiliation">

In our example, the sAMAccountName and eduPersonAffiliation directory attributes are retrieved from the LDAP directory to be used as the basis for building your SAML attributes. You may need to change these, and/or add others to the list, depending on which attributes are stored in your LDAP directory and what your SAML attribute requirements are. sAMAccountName (the username of the authenticating user) is used in this example as a source attribute for the SAML attribute eduPersonPrincipalName. eduPersonAffiliation, a multi-valued directory attribute containing one or more user affiliations, such as (staff, member) or (student, member), is used in this example as a source attribute for the SAML attribute eduPersonScopedAffiliation.

eduPersonScopedAffiliation

Assuming you have a DataConnector configuration with id="myLDAP", and the LDAP has been populated with the eduPersonAffiliation attribute for all your users, then you can use the eduPersonAffiliation attribute as the basis to generate eduPersonScopedAffiliation with the following snippet in attribute-resolver.xml:

 <AttributeDefinition xsi:type="Scoped" id="eduPersonScopedAffiliation" scope="%{idp.scope}">
     <InputDataConnector ref="myLDAP" attributeNames="eduPersonAffiliation"/>
 </AttributeDefinition>

If the LDAP has not been populated with eduPersonAffiliation and it is not possible to arrange for it to be populated then you may need to use an alternative attribute definition for eduPersonAffiliation, based on other attributes or groups in the LDAP directory.

eduPersonTargetedID

This attribute again depends on having a DataConnector configuration to connect to your LDAP. It also requires a ComputedId DataConnector. See the DataConnector with id="computed" in the example above.

You should not need to make any changes to that; but you will need to make some changes to the file saml-nameid.properties. In saml-nameid.properties, set the idp.persistentId.sourceAttribute be the name of a directory attribute suitable for use as a source attribute for eduPersonTargetedID and other persistent SAML attributes. Whichever source attribute is chosen, it should not change over time. Commonly the username is used; in OpenLDAP this is often called uid.

 idp.persistentId.sourceAttribute=uid

In Active Directory, the username is often called sAMAccountName, although this has been known to change during the lifetime of a user's account. Depending on your system, either objectGUID or objectSid could be used.

The objectGUID is binary, so if it is to be used as the source attribute it should be declared as binary by adding this line to the LDAP DataConnector with id="myLDAP":

 <LDAPProperty name="java.naming.ldap.attributes.binary" value="objectGUID"/>

If you use objectSid, you'll need to add a similar element to the LDAP DataConnector.

You also need to set the property idp.persistentId.salt in %{idp.home}/credentials/secrets.properties. It is a random string of at least 16 bytes which you choose. It should be kept secret.

 idp.persistentId.salt=0123456789abcdef

Important: if you are migrating from an earlier deployment you should use the same source attribute and salt value as you used previously, and set idp.persistentId.encoding = BASE64 in saml-nameid.properties, to ensure that the same values are generated for each of your users as were previously. This is necessary to retain access to personalisations saved on SPs that are keyed to eduPersonTargetedID values.

 idp.persistentId.encoding = BASE64

And here then is the configuration snippet in attribute-resolver.xml for eduPersonTargetedID:

 <AttributeDefinition xsi:type="SAML2NameID" id="eduPersonTargetedID"
     nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">
     <InputDataConnector ref="computed" attributeNames="computedId"/>
     <AttributeEncoder xsi:type="SAML1XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10"/>
     <AttributeEncoder xsi:type="SAML2XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10"
                       friendlyName="eduPersonTargetedID"/>
 </AttributeDefinition>
Attribute filter configuration

Details of the Shibboleth IdP attribute filter configuration are given in the Shibboleth attribute filter configuration documentation. The attribute filter configuration determines which attributes are released to which service providers, and is configured in the conf/attribute-filter.xml file. Most service providers in the UK federation require the attribute eduPersonScopedAffiliation with an affiliation value equivalent to full membership, eg. member, staff or student. The affiliation values released for a given user must be determined on the basis of the user's genuine affiliation with your organisation from your organisation's point of view.

In general the UK federation considers there to be very little personally identifying information carried by either eduPersonScopedAffiliation or eduPersonTargetedID so considers it safe to release them to any SP; the following configuration snippet does just that. However, your organisation should do its own risk analysis in consultation with its data protection officer rather than taking our word for it.

Note that this snippet would release these two attributes to any SP with which the IdP successfully authenticated; this might be a UK federation SP, or an SP imported from another federation via eduGAIN interfederation, or another SP for which the IdP has the metadata configured one way or another. More sophisticated attribute filters are possible; please see the Shibboleth documentation.

This simple example releases eduPersonScopedAffiliation and eduPersonTargetedID to any SP.

 <AttributeFilterPolicyGroup id="ShibbolethFilterPolicy"
        xmlns="urn:mace:shibboleth:2.0:afp"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="urn:mace:shibboleth:2.0:afp
        http://shibboleth.net/schema/idp/shibboleth-afp.xsd">

    <!-- Release eduPersonScopedAffiliation and eduPersonTargetedID attributes to any SP. -->
    <AttributeFilterPolicy id="releaseToAnyone">
        <PolicyRequirementRule xsi:type="ANY" />
        <AttributeRule attributeID="eduPersonScopedAffiliation" permitAny="true" />
        <AttributeRule attributeID="eduPersonTargetedID" permitAny="true" />
    </AttributeFilterPolicy>

 </AttributeFilterPolicyGroup>