This how-to applies to Shibboleth Identity Provider v4 and above and can be used to integrate the authentication flows with other SAML2 compliant identity providers such as SimpleSAMLphp or Microsoft Azure. There is a far more detailed guide to integrating with Azure at Using SAML Proxying in the Shibboleth IdP to connect with Azure AD.
Note: this is quite a new process and the use of terminology in the document may vary between organisations or SAML2 implementations. Please feel free to clarify or improve on the wording!
Delegating Authentication to another IdP
This process will absolve your Identity Provider (IdP) of the process of authenticating the user, instead relying on another SAML2 IdP to do that job. The resulting Assertion is used to generate the user's local username which is then used in the standard Attribute Resolution process.
In essence, your IdP well become a Service Provider (SP) to a second IdP.
This method describes extracting the username from an Attribute in the Assertion. It's also possible to use the Subject.
In this example, the following entities and attributes are in use:
- Original IdP EntityID:
- Upstream IdP EntityID:
- Joining attribute (common to both services):
- Authentication request hits IdP
- IdP issues a redirect to Upstream IdP
- User authenticates (or reuses session?) against Upstream IdP and generates an Assertion
- Assertion consumed from upstream IdP
- Assertion filtered before use
- Attribute extracted from upstream Assertion for use as real username:
- Configure attribute-based subject c14n.
- Look through list of
AttributesToResolvein the resolver and resolve each one.
- Look through list of resulting attributes in
AttributeSourceIdsand pick first valid one to be the principal's name to then be used later
- Resulting trusted real username used as
$resolutionContext.principal(eg. existing LDAP data connector, etc.) during "standard" attribute resolution process
- A working Identity Provider at V4 or above
- A SAML2 compliant Identity Provider to delegate to
- A suitable attribute available to both IdPs to use as a "joining" attribute (so the other IdP can provide a value which can be looked up in the main IdP's connected data source)
Update your IdP's metadata
As your IdP will need act as an SP, you'll need extra blocks in your entity's metadata. Create a new
sp-metadata.xml (or update your existing
idp-metadata.xml but consider whether this should be included in multi-lateral federation agreements) file to include a
<SPSSODescriptor> block. You'll need to copy the signing and encryption certificates from the IdP part of the metadata and replace the base URI (
https://idp.example.ac.uk/idp) with the base of your IdP.
Register your IdP with the upstream IdP
Use your updated metadata to register the IdP/SP with the IdP you'd like to delegate to and configure it to send a value to use an username (eg.
You may just need to supply the EntityID and Assertion Consumer Service URL:
- EntityID: same as for your IdP
- Assertion Consumer Service:
Register the upstream IdP's metadata locally
If your upstream IdP is not already known by some other means, then register the upstream IdP, too. This is handled just like any other metadata and can be included in your
metadata-providers.xml as a new
<MetadataProvider> block. For example:
The following changes need to be made to the IdP to support this workflow:
- Enable the SAML authentication flow
- Configure to which Entity to delegate
- Update attribute filter to allow incoming attributes to be ingested
- Set up attribute extraction through Subject Canonicalisation (c14n and resolver)
Enable the SAML authentication flow
authn/saml-authn-config.xml to set the EntityID of the upsteam IdP. Uncomment the
shibboleth.authn.SAML.discoveryFunction bean and edit the
Enable the flow by updating
Update Attribute Filter
The IdP will not ingest attributes from the Upstream IdP unless they're allowed in by a filter. Add a new
<AttributeFilterPolicy> to permit trusted attributes to be handled:
This workflow takes the incoming assertion and extracts some data from it to work out the canonical (authoritative) username of the authenticated user. In this very simple case we're using
uid (unscoped username).
Add a new
<AttributeDefinition> to the
attribute-resolver.xml which will transform the
uid attribute from the Subject (the filtered data from the incoming assertion) into a
proxied-uid attribute for use elsewhere:
With the Subject, configure which attributes to fire in the resolver to work out what's going on. Set
c14n/attribute-sourced-subject-c14n-config.xml to the id of the new
This may need to include more attributes depending on how much work you need to do to turn the incoming attribute into the real username that you need later.
AttributeSourceIds value to which newly resolved attributes you would treat as the real username. This is probably the same or a subset of
At this point you should have a valid locally understood username to pass into the "normal" resolver that already works, which is now available from places like:
Restart your IdP and test!
Your existing resolver should still work using