This guidance is for older versions of the IdP. The most recent user contributed guidance can be found here: SAML Proxying EntraID / Azure with the Shibboleth IdP
A French version of this document can be found on the CANARIE website.
Note |
---|
Please read and follow the documentation first, before or along with using this example. This documentation is not maintained by the development team and may not be entirely accurate or consistent with the software at any given time. It is a complement to the documentation, not a replacement for it. It is currently out of date with respect to some improvements made in V4.1. |
Table of Contents |
---|
Overview
This configuration recipe of the Shibboleth IdP leverages the SAML proxying features such that Azure AD can be used for sign-in while Shibboleth handles the features many R&E federation's trust models value. Using this approach uses just the IdP as a SAML proxy without the necessity of extra elements.
...
Acknowledgements: Thanks to contributors Former user (Deleted), the Shibboleth team, and others for guidance and input on the material.
IdP Proxying: Appearances and Perspectives
Proxying techniques are confusing at times and it is helpful to understand the approach and your perspective:
...
- The entity registered in the R&E federation is the Shibboleth IdP, built for and by the R&E community and should meet all technical requirements as does any other Shibboleth IdP
- Alignment to any federation baseline expectations is not just software but also how it's operated and managed and is in the hands of the IdP operator like any other IdP.
IdP Proxying: What a Proxy Flow Looks Like
When the user initiates sign-on the following usually happens:
- An Authentication request arrives at Shibboleth IdP
The Shibboleth IdP observes it's configured for SAML sign on and redirects to an upstream IdP (Azure AD). Settings for this are controlled in
idp.properties
authn/saml-authn-config.xml
- User Authenticates or has an existing session at upstream IdP (Azure AD)
- The upstream IdP (Azure AD) constructs a SAML Assertion with one or more attributes and is sent with the user to the Shibboleth IdP
- The Shibboleth IdP receives the assertion and:
verifies that the assertion arrives from an entity it trusts as configured in
metadata-providers.xml
- filters the assertion according to rules in
attribute-filter.xml
- Extracts the real user as configured in attribute-based subject c14n.
- Looks through list of
AttributesToResolve
in the resolver and resolves each one. - Looks through list of resulting attributes in
AttributeSourceIds
and picks the first valid one to be the principal's name to be used later
- Looks through list of
- Resulting trusted real username is used as
$resolutionContext.principal
(eg. existing LDAP data connector, etc.) during "standard" attribute resolution process
Implementing the Solution
Prerequisites
Be sure to have these assets in place and appropriate access to them before you start:
- A working Shibboleth Identity Provider at V4 or above running somewhere.
- An active Azure AD tenant that you have administrative control in
- The ability in Azure AD to create an enterprise Non-Gallery SAML App
- A suitable attribute available to both IdPs to use as a "joining" attribute used in local lookups if necessary.
Terms and Settings
This document refers to some key settings and terms described here. For your installation have these on hand to speed up configuration:
- Your original IdP EntityID:
https://idp.example.com/idp
- Your Upstream IdP EntityID which is Azure AD Identifier:
https://sts.windows.net/<sts_tenant_id>/
- sts_tenant_id can be found most easily by creating a relying parting in Azure AD to work with:
- sign into the Azure AD Portal -> choose Enterprise Applications -> Create New Application > Non Gallery Application → Actually create one → select SAML Sign On - > select SAML Sign On settings
- Section 4 contains the Azure AD Identifier which includes the trailing slash
- sts_tenant_id can be found most easily by creating a relying parting in Azure AD to work with:
- The Proxy Joining attribute common to both services:
SamAccountName
is often a good choice and appears as 'name' in claims.- will exist as a 'scoped' username
- the scope being that of the domain used on-premises and is usually internet friendly (not something.local or something.int)
- Relying Party/Service Provider Microsoft will use "Relying Party" at times to mean "Service Provider"
Steps and Tasks
Step 1. Configuring Trust Between Azure AD and the Shibboleth IdP
There are 3 main trust-related configurations to adjust:
...
3. the Azure AD trust to the Shibboleth IdP as a Relying Party
Trust Task: 1. Update your IdP's metadata
As your IdP will need act as an SP, you'll need extra blocks in your entity's metadata.
...
Code Block | ||||
---|---|---|---|---|
| ||||
<EntityDescriptor entityID="https://idp.example.com/idp" ...> <!-- Already present IdP data --> <IDPSSODescriptor ...> ... </IDPSSODescriptor> <AttributeAuthorityDescriptor> ... </AttributeAuthorityDescriptor> <!-- New SP block --> <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> <KeyDescriptor use="signing"> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate> ...Signing Certificate from IdP... </ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </KeyDescriptor> <KeyDescriptor use="encryption"> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate> ...Encryption Certificate from IdP... </ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </KeyDescriptor> <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://idp.example.com/idp/profile/Authn/SAML2/POST/SSO" index="0"/> </SPSSODescriptor> </EntityDescriptor> |
Trust Task: 2. Register your IdP with Azure AD
An Azure AD Enterprise Application needs to be created of type 'Non-Gallery Application' and configured for SAML.
...
Keep this Relying Party editing environment open for the next step.
Trust Task: 3. Register the upstream IdP's metadata locally
Your Shibboleth IdP doesn't know of the Azure AD IdP so you need to register it locally. This is handled just like any other metadata and can be included in your metadata-providers.xml as a new <MetadataProvider>
element. For example:
...
Note |
---|
Note!
|
Trust Task: 4. Configure Azure AD Attribute Release to the Shibboleth IdP
While still in the edit mode of the Relying Party, configure the necessary attributes needed for the Shibboleth IdP operation.
...
Info |
---|
user.userprincipalname is the usual choice for the main user identifier but review your practices carefully around its use and potential re-use. This is going to be especially critical around MFA and assurance attestations to ensure they have a unique identifier that is unchanging. |
Step 2. Configure the IdP for Proxing Behaviour
The following changes are needed to adjust the IdP to proxying behaviour:
- Changing the authentication flow to SAML authentication
- Configuring which Entity to delegate to for the flow
- Update attribute filter to allow incoming attributes to be ingested
- Set up attribute extraction through Subject Canonicalisation (c14n and resolver)
Proxy Task 1. Change the IdP authentication flow to SAML
There are three steps for this task:
...
2. Enable the flow by updating idp.authn.flows
in idp.properties to set it to SAML:
idp.authn.flows=SAML
Proxy Task 2. Update Your Attribute Filter
The IdP will not ingest attributes from the Azure AD Upstream IdP unless they're allowed in by a filter.
...
Code Block | ||
---|---|---|
| ||
<AttributeFilterPolicy id="FilterPolicyObject-Proxy-FromAzure-byIssuer-Type"> <PolicyRequirementRule xsi:type="Issuer" value="https://sts.windows.net/<sts_tenant_id>/" /> <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> </AttributeFilterPolicy> |
Proxy Task 3. Enable IdP to Recognize Azure AD Claims
Azure AD issues SAML assertions, however they are presented in an Azure/WS-Fed-centric naming convention (as "claims").
...
Now that we have the the IdP able to interpret claims from Azure AD, we need to turn our attention to using them for user canonicalization and for populating our attributes.
Proxy Task 4. Subject Canonicalisation
This workflow takes the incoming assertion and extracts some data from it to work out the canonical (authoritative/normalized) username of the user logging in from Azure.
...
$resolutionContext.principal
Proxy Task 5. Configuring Attribute pass-through and/or hybrid resolving
Attributes originating from Azure AD are referenced in attribute-resolver.xml like this:
...
Code Block | ||
---|---|---|
| ||
<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" /> |
Proxy Task 6. Handling REFEDS AuthnContext Requests (optional)
Azure does not currently have a documented way to influence the behavior of the AuthnContext in their SAML assertions. However, Shibboleth provides the means to translate proxy requests and responses via authn/authn-comparison.xml. The example below handles REFEDS MFA requests:
Code Block | ||
---|---|---|
| ||
<util:map id="shibboleth.PrincipalProxyRequestMappings"> <entry> <key> <bean parent="shibboleth.SAML2AuthnContextClassRef" c:classRef="https://refeds.org/profile/mfa" /> </key> <list> <bean parent="shibboleth.SAML2AuthnContextClassRef" c:classRef="http://schemas.microsoft.com/claims/multipleauthn" /> </list> </entry> </util:map> <util:map id="shibboleth.PrincipalProxyResponseMappings"> <entry> <key> <bean parent="shibboleth.SAML2AuthnContextClassRef" c:classRef="http://schemas.microsoft.com/claims/multipleauthn" /> </key> <list> <bean parent="shibboleth.SAML2AuthnContextClassRef" c:classRef="https://refeds.org/profile/mfa" /> </list> </entry> </util:map> |
Update the support matrix for the SAML authentication flow to understand the REFEDS MFA profile
(for v4.0.1) Update the authn/SAML bean in authn/general-authn.xml so it understands the REFEDS MFA profile by adding a supportedPrincipals property:
...
Changes required in v4.1 may be different and you should look at the authn.properties file. More details here: SAMLAuthnConfiguration
Testing
Restart your IdP for your changes to take effect. Because this is a SAML proxy configuration it doesn't make sense to use aacli
since it won't have the required information available to it.
Some sites have a developer account which has a tenant that can test entirely isolated from the production tenant. Alternatively you can create a different Azure AD non-gallery SAML app per IdP – one for production, one for pre-production etc. There's no hard and fast rule on the best way however the developer route is free and provides a great model for isolation between credentials as it's a different cookie domain entirely.
Related content / Recommended Reading
- Shibboleth related:
- Azure AD SSO and SAML Related:
...