User authentication
The Shibboleth v4 IdP software natively supports four types of password authentication, being LDAP, JAAS, Kerberos and HTPasswd. For detailed configuration information please see the Shibboleth IdP v4 documentation pages:
- IdP v4 Password Authentication Configuration
- IdP v4 LDAP Configuration
- IdP v4 JAAS Configuration
- IdP v4 Kerberos Configuration
- IdP v4 HTPasswd Configuration
Of the above, we expect more UK federation IdP operators to use Active Directory or another LDAP (Lightweight Directory Access Protocol) directory for user authentication and attribute generation, so we focus on that here.
Proxying with Azure Active Directory (AAD) is now a popular choice, and has been simplified by the introduction of a proxying module in Shibboleth IdP v4. This allows you to offload user authentication onto AAD and make use of its MFA (multi-factor authentication) services. We include here configuration guidance for authentication and attribute release with AAD; and for hybrid attribute release using a combination of AAD and Shibboleth's native LDAP support.
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>
Azure Active Directory
For detailed configuration information please see the Shibboleth IdP v4 documentation page:
Please also see this "how-to" guide on the Shibboleth wiki for information about configuring Azure as a user authentication and attribute source. Note that the guide is out of date with respect to changes from Shibboleth IdP v4.1 onwards. In this section we provide advice that incorporates those changes and is up to date as of v4.3.
Configuration stages
We provide here guidance for configuring Azure AD as an authentication source for the Shibboleth IdP, and also as an attribute source. When AAD is the authentication source and the sole attribute source then we refer to it as pass-through proxying.
We also provide guidance for configuring Azure AD as authentication source and (possibly) attribute source in combination with Active Directory (or other LDAP directory) as attribute source; this we refer to as hybrid proxying.
When hybrid proxying we choose a single attribute from AAD which corresponds to (and typically would be synchronised with) an attribute in Active Directory/other LDAP directory. We call this the join attribute; we suggest using user.onpremisessamaccountname
as the join attribute, and have done so in the examples here.
If you plan to use Active Directory (or other LDAP directory) as an attribute source then it may be easier to configure the IdP to authenticate and resolve attributes via LDAP first, according to our Active Directory/LDAP configuration guidance, then switch to hybrid proxying using the configuration stages below.
- Configure Trust between AAD and Shibboleth IdP
- Change IdP authentication flow to SAML
- Test authentication
- Configure AAD attribute release to the Shibboleth IdP
- Release attributes from AAD
- Release attributes from directory
- Update IdP attribute filter
Configure Trust between AAD and Shibboleth IdP
These first three stages involve registering the Shibboleth IdP with Azure AD and providing the Shibboleth IdP and Azure AD with each other's metadata.
Register Shibboleth IdP with AAD
- Sign into the Azure Active Directory portal
- Click Azure Active Directory
- Click Enterprise applications
- Click New application
- Click Create your own application
- Choose the "Integrate any other application you don't find in the gallery (Non-gallery)" radio button
- Type in a name for your IdP eg. Shibboleth IdP
- Click Create
You should then see an overview of the application with several options under the "Getting Started" heading.
- In the "Set up single sign on" option click "Get started"
- Under the "Select a single sign-on method" heading click SAML
- Under "Set up Single Sign-On with SAML" click "Edit" in "Basic SAML Configuration"
- Under "Basic SAML Configuration" click "Add identifier". Copy your Shibboleth IdP entityID into the box and click Add identifier again
- Still under "Basic SAML Configuration" click "Add reply URL". Paste your IdP's
<AssertionConsumerService>
URL as created above into the box - Click Save
- Click the cross at top right of the page to exit Basic SAML Configuration, and keep the SAML-based Sign-on page open for the next step
Edit Shibboleth IdP metadata provider configuration
Still in Azure, under "SAML Certificates" next to "Federation Metadata XML" click "Download" to download the Azure IdP metadata. The file will be easier to edit if you use an XML editor to format or "pretty print" the metadata. Edit the metadata file. You can remove some unnecessary elements to reduce the size of the file and make it easier to edit and understand; the unnecessary elements are:
- the
Signature
element at the top of the file - the
Fed:ClaimTypesOffered
section
Then make additions as follows:
- Add this namespace to the
EntityDescriptor
:xmlns:shibmd="urn:mace:shibboleth:metadata:1.0"
- Add an
<Extensions>
block inside theIDPSSODescriptor
containing aScope
element with your Shibboleth IdP's scope, eg.
<Extensions> <shibmd:Scope regexp="false">example.ac.uk</shibmd:Scope> </Extensions>
Save the file and copy it to to the Shibboleth IdP's %{idp.home}/metadata/
directory; name the file AAD.xml
.
Edit the Shibboleth IdP's %{idp.home}/conf/metadata-providers.xml
file and add an entry for the Azure IdP metadata, eg:
<!-- AD.xml - local metadata file for test Azure Active Directory --> <MetadataProvider id="LocalMetadata" xsi:type="FilesystemMetadataProvider" metadataFile="%{idp.home}/metadata/AAD.xml"/>
Note about Azure AD certificates: the Azure AD certificate has a three-year lifetime, meaning that the IdP administrators need to handle Azure AD certificate rollover every three years shortly before the certificate is due to expire to maintain trust between Shibboleth and AAD.
Edit Shibboleth IdP metadata file
- Edit the
%{idp.home}/metadata/idp-metadata.xml
file to include an<SPSSODescriptor>
block - Copy the
<KeyDescriptor>
elements containing the signing and encryption certificates from the IdP part of the metadata into the<SPSSODescriptor>
block - Add an
<AssertionConsumerService>
URL immediately before the closing</SPSSODescriptor>
tag of the formhttps://idp.example.ac.uk/idp/profile/Authn/SAML2/POST/SSO
, replacingidp.example.ac.uk
with your IdP hostname
Change IdP authentication flow to SAML
In this step we change the IdP's authentication flow to SAML, to enable it to proxy with Azure AD; and provide the IdP with the Azure AD entityID.
- Edit the Shibboleth IdP's
%{idp.home}/conf/authn/authn.properties
file - change the value of
idp.authn.flows
toSAML
:
idp.authn.flows=SAML
- set the value of
idp.authn.SAML.proxyEntityID
to the AAD IdP entityID as found in the AAD IdP metadata, eg:
idp.authn.SAML.proxyEntityID=https://sts.windows.net/xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx/
Test authentication
At this point users configured in AAD should be able to authenticate with the IdP using AAD as an authentication proxy. Test authentication using the UK federation test SP. You don't expect attributes to be released at this stage, but users should be authenticated and redirected to the test SP page. Make sure this is working before moving on the next section.
Information about testing using the UK federation test SP is in the Testing IdP deployments section.
Configure AAD attribute release to the Shibboleth IdP
As mentioned previously, if all the attributes we wish to release to service providers are stored in AAD then we call it pass-through proxying. If some or all of the attributes we wish to release are stored in Active Directory or other LDAP directory then we call it hybrid proxying. We might combine the two approaches and release attributes from both AAD and Active Directory/other directory.
Pass-through proxy
All attributes originate from Azure AD and must be released to the Shibboleth IdP, which will transform them and release to the SP. Configure attribute release in AAD as follows:
- In Azure AD click "Enterprise application"
- Click the name of the enterprise application you created previously, eg. "Shibboleth IdP"
- Under "Set up single sign on" click "Get started"
- Click "Edit" on "Attributes & Claims"
- Configure release of all the attributes you want to release to SPs
Hybrid proxy
One attribute is needed from AAD which can then be used for user lookup in Active Directory/other LDAP directory: the join attribute. We suggest using user.onpremisessamaccountname
as the join attribute. However if a combined approach, ie. releasing attributes from both AAD and a directory, is being taken then more attributes may be released from AAD as above. Configure release of the join attribute in AAD as follows:
- In Azure AD click "Enterprise application"
- Click the name of the enterprise application you created previously, eg. "Shibboleth IdP"
- Under "Set up single sign on" click "Get started"
- Click "Edit" on "Attributes & Claims"
- Configure release of
user.onpremisessamaccountname
or other attribute designated as join attribute
Update IdP attribute filter
You need to update the IdP attribute filter to permit attributes to be released by Azure AD to the IdP. Edit %{idp.home}/conf/attribute-filter.xml
and add a suitable AttributeFilterPolicy
rule. You can base it on this example, setting value
to the AAD IdP entityID as found in the AAD IdP metadata:
<AttributeFilterPolicy id="FilterPolicyObject-Proxy-FromAzure-byIssuer-Type"> <PolicyRequirementRule xsi:type="Issuer" value="https://sts.windows.net/xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx/" /> <AttributeRule attributeID="azureDisplayname" permitAny="true" /> <AttributeRule attributeID="azureGivenname" permitAny="true" /> <AttributeRule attributeID="azureSurname" permitAny="true" /> <AttributeRule attributeID="azureAuthnmethodsreferences" permitAny="true" /> <AttributeRule attributeID="azureIdentityprovider" permitAny="true" /> <AttributeRule attributeID="azureTenantid" permitAny="true" /> <AttributeRule attributeID="azureEmailaddress" permitAny="true" /> <AttributeRule attributeID="azureObjectidentifier" permitAny="true" /> <AttributeRule attributeID="azureName"> <PermitValueRule xsi:type="ScopeMatchesShibMDScope" /> </AttributeRule> <AttributeRule attributeID="azureOnPremisessAMAccountName" permitAny="true" /> </AttributeFilterPolicy>
You probably don't need all the attributes above, and you may want to use others not listed above. If you plan to base some or all of your SAML attributes for release to service providers on attributes in Azure AD then you will need to include all the Azure AD attributes necessary for that in your attribute filter.
Note that the ScopeMatchesShibMDScope
rule above for azureName
is based on the assumption that your Azure AD uses the same scope as your Shibboleth IdP. If it does not then you will need to use another rule, such as permitAny="true"
.
If you plan to base all your SAML attributes for release to service providers on the attributes in Active Directory (or other LDAP directory) then you only need a single attribute from Azure AD to use as the "join" attribute to retrieve attributes from the directory. You can use the example below to do this, based on our recommendation of user.onpremisessamaccountname
as the join attribute. Set value
to the AAD IdP entityID as found in the AAD IdP metadata.
<AttributeFilterPolicy id="FilterPolicyObject-Proxy-FromAzure-byIssuer-Type"> <PolicyRequirementRule xsi:type="Issuer" value="https://sts.windows.net/xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx/" /> <AttributeRule attributeID="azureOnPremisessAMAccountName" permitAny="true" /> </AttributeFilterPolicy>
Configure IdP to recognise AAD claims
Add attribute mapping file
Create a file in %{idp.home}/conf/attributes
called azureClaims.xml
. This file includes all of the attributes from Azure AD that you need to use in the Shibboleth IdP attribute resolver. The example below is not exhaustive. We need to add sAMAccountName to this.
There needs to be a transcoder bean for each attribute that is being retrieved from Azure AD, whether it is to be used just as a join attribute for retrieving attributes from directory, or as the basis of an attribute definition in attribute-resolver.xml.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd" default-init-method="initialize" default-destroy-method="destroy"> <bean parent="shibboleth.TranscodingRuleLoader"> <constructor-arg> <list> <!-- claims relevant to person record --> <bean parent="shibboleth.TranscodingProperties"> <property name="properties"> <props merge="true"> <prop key="id">azureOnPremisessAMAccountName</prop> <prop key="transcoder">SAML2StringTranscoder</prop> <prop key="saml2.name">http://schemas.xmlsoap.org/ws/2005/05/identity/claims/samaccountname</prop> <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop> <prop key="displayName.en">onPremises sAMAccountName</prop> <prop key="description.en">Azure on-premises sAMAccountName</prop> </props> </property> </bean> <bean parent="shibboleth.TranscodingProperties"> <property name="properties"> <props merge="true"> <prop key="id">azureName</prop> <prop key="transcoder">SAML2ScopedStringTranscoder</prop> <prop key="saml2.name">http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name</prop> <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop> <prop key="displayName.en">Name</prop> <prop key="description.en">Azure UPN of an account expected to be scoped thus transcoded that way</prop> </props> </property> </bean> <bean parent="shibboleth.TranscodingProperties"> <property name="properties"> <props merge="true"> <prop key="id">azureEmailaddress</prop> <prop key="transcoder">SAML2StringTranscoder</prop> <prop key="saml2.name">http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress</prop> <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop> <prop key="displayName.en">Mail</prop> <prop key="description.en">Azure emailaddress field of an account</prop> </props> </property> </bean> <bean parent="shibboleth.TranscodingProperties"> <property name="properties"> <props merge="true"> <prop key="id">azureDisplayname</prop> <prop key="transcoder">SAML2StringTranscoder</prop> <prop key="saml2.name">http://schemas.microsoft.com/identity/claims/displayname</prop> <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop> <prop key="displayName.en">Mail</prop> <prop key="description.en">Azure displayname field of an account</prop> </props> </property> </bean> <bean parent="shibboleth.TranscodingProperties"> <property name="properties"> <props merge="true"> <prop key="id">azureGivenname</prop> <prop key="transcoder">SAML2StringTranscoder</prop> <prop key="saml2.name">http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname</prop> <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop> <prop key="displayName.en">Given name</prop> <prop key="description.en">Azure given name of an account</prop> </props> </property> </bean> <bean parent="shibboleth.TranscodingProperties"> <property name="properties"> <props merge="true"> <prop key="id">azureSurname</prop> <prop key="transcoder">SAML2StringTranscoder</prop> <prop key="saml2.name">http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname</prop> <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop> <prop key="displayName.en">Surname</prop> <prop key="description.en">Azure surname of an account</prop> </props> </property> </bean> <!-- default claims from Azure for any entity --> <bean parent="shibboleth.TranscodingProperties"> <property name="properties"> <props merge="true"> <prop key="id">azureTenantid</prop> <prop key="transcoder">SAML2StringTranscoder</prop> <prop key="saml2.name">http://schemas.microsoft.com/identity/claims/tenantid</prop> <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop> <prop key="displayName.en">Tenant ID</prop> <prop key="description.en">Azure tenantid</prop> </props> </property> </bean> <bean parent="shibboleth.TranscodingProperties"> <property name="properties"> <props merge="true"> <prop key="id">azureObjectidentifier</prop> <prop key="transcoder">SAML2StringTranscoder</prop> <prop key="saml2.name">http://schemas.microsoft.com/identity/claims/objectidentifier</prop> <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop> <prop key="displayName.en">Object Identifier</prop> <prop key="description.en">Azure object identifier of an account</prop> </props> </property> </bean> <bean parent="shibboleth.TranscodingProperties"> <property name="properties"> <props merge="true"> <prop key="id">azureIdentityprovider</prop> <prop key="transcoder">SAML2StringTranscoder</prop> <prop key="saml2.name">http://schemas.microsoft.com/identity/claims/identityprovider</prop> <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop> <prop key="displayName.en">Identity Provider entityid</prop> <prop key="description.en">Azure entityID of the tenant in Azure</prop> </props> </property> </bean> <bean parent="shibboleth.TranscodingProperties"> <property name="properties"> <props merge="true"> <prop key="id">azureAuthnmethodsreferences</prop> <prop key="transcoder">SAML2StringTranscoder</prop> <prop key="saml2.name">http://schemas.microsoft.com/claims/authnmethodsreferences</prop> <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop> <prop key="displayName.en">Authnmethodsreferences</prop> <prop key="description.en">Azure authentication method (password, modern auth? etc)</prop> </props> </property> </bean> </list> </constructor-arg> </bean> </beans>
If you only plan to release attributes from Active Directory/other LDAP directory then you only need to include the join attribute in the attribute mapping file, for example:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd" default-init-method="initialize" default-destroy-method="destroy"> <bean parent="shibboleth.TranscodingRuleLoader"> <constructor-arg> <list> <!-- claims relevant to person record --> <bean parent="shibboleth.TranscodingProperties"> <property name="properties"> <props merge="true"> <prop key="id">azureOnPremisessAMAccountName</prop> <prop key="transcoder">SAML2StringTranscoder</prop> <prop key="saml2.name">http://schemas.xmlsoap.org/ws/2005/05/identity/claims/samaccountname</prop> <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop> <prop key="displayName.en">onPremises sAMAccountName</prop> <prop key="description.en">Azure on-premises sAMAccountName</prop> </props> </property> </bean> </list> </constructor-arg> </bean> </beans>
Add reference to attribute mapping file
Update %{idp.home}/conf/attributes/default-rules.xml
to refer to the new attribute mapping file by adding this line after the last import:
<import resource="azureClaims.xml" />
Release attributes from AAD
Follow the steps in this section to release attributes that are stored in Azure AD.
Update IdP attribute resolver
Add a data connector to %{idp.home}/conf/attribute-resolver.xml
to reveal the attributes from Azure AD as follows:
<DataConnector id="passthroughAttributes" xsi:type="Subject" exportAttributes="azureName azureEmailaddress azureDisplayname azureGivenname azureSurname azureTenantid azureObjectidentifier azureIdentityprovider azureAuthnmethodsreferences" />
You only need to include the attributes stored in Azure AD that you will be releasing to SPs. If you are using a join attribute to retrieve attributes from Active Directory/other LDAP directory then you do not need to include it. If you are only releasing attributes that are stored in Active Directory/other LDAP directory then you do not need the above passthroughAttributes
DataConnector
at all.
Add attribute definitions as follows. Notice that the value of principalAttributeName
will be one of the exported attributes from the above DataConnector
:
<AttributeDefinition xsi:type="SubjectDerivedAttribute" forCanonicalization="false" id="mail" principalAttributeName="azureEmailaddress" /> <AttributeDefinition xsi:type="SubjectDerivedAttribute" forCanonicalization="false" id="displayName" principalAttributeName="azureDisplayname" /> <AttributeDefinition xsi:type="SubjectDerivedAttribute" id="eduPersonPrincipalName" principalAttributeName="azureName" />
Release attributes from directory
Follow the steps in this section to release attributes stored in Active Directory, or other LDAP directory. As has been discussed previously, you need to select an attribute in AAD that corresponds to an attribute in the LDAP directory and acts as a username to use as your join attribute. We are using user.onpremisessamaccountname
as the "join" attribute in our examples here.
Configure join attribute and subject canonicalisation
To configure the join attribute, edit %{idp.home}/conf/c14n/subject-c14n.properties
, putting the attribute being used for join in the idp.c14n.attribute.attributeSourceIds
property, eg.
idp.c14n.attribute.attributeSourceIds = azureOnPremisessAMAccountName # Allows direct use of attributes via SAML proxy authn, bypasses resolver idp.c14n.attribute.resolveFromSubject = true idp.c14n.attribute.resolutionCondition = shibboleth.Conditions.FALSE
We need to perform subject canonicalisation on the "join" attribute. Edit %{idp.home}/conf/c14n/subject-c14n.xml
and uncomment this bean:
<!-- Remove comment tags to enable Attribute-based c14n --> <bean id="c14n/attribute" parent="shibboleth.PostLoginSubjectCanonicalizationFlow" />
Update IdP attribute resolver
To configure attribute resolution for attributes stored in Active Directory/other LDAP directory, please refer to our Active Directory and other LDAP directories section. You will need to configure authentication and attribute release as described in that section.
Update IdP attribute filter
To configure attribute filtering, ie. to determine which attributes are released to which SPs, please refer to our Active Directory and other LDAP directories attribute filter configuration section, for which configuration is the same.