SAMLAuthnConfiguration
Current File(s): conf/authn/authn.properties, conf/relying-party.xml
Format: Properties, Native Spring
Overview
The authn/SAML login flow supports the use of a separate SAML 2.0 Identity Provider to authenticate the subject, with the IdP acting as a SAML proxy. This flow provides native SAML support with additional features and flexibility without the need to deploy a separate SAML Service Provider implementation along with the IdP.
The majority of this flow's behavior is actually derived from pre-existing configuration sources, in particular the use of SAML metadata (but for the IdP rather than the more usual SP metadata), and, if required, the use of https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199508044 to override behavior for specific IdPs.
The rest of the configuration needed is generally for the decoding and mapping/propagation of Attribute data from SAML, into the IdP, and usually on to SPs, which is common to most proxy authentication scenarios.
Be aware that the issues raised by https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199501597 are fatal to this feature. If you have not yet deployed the filter provided as a workaround (possibly including accomodations for older Apple browsers), you will experience sporadic failures with this feature during the SAML POST back to the proxying Shibboleth IdP.
General Configuration
There are only two core requirements for this flow to operate:
The entityID of the Identity Provider to use must be known or determined “somehow”.
SAML metadata for that Identity Provider must be available via the usual https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199506698.
The entityID to use can be established either via static configuration, a lookup function, or prior to this flow running by providing some form of IdP Discovery service and toggling the flow's discoveryRequired property (as discussed more generally in the https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199505085 topic).
When proxying all traffic to a different back-end operated by the same organization, the static configuration approach of a property is usually sufficient. For such simpler cases, the idp.authn.SAML.proxyEntityID property can be set, to directly specify an IdP to use, or a bean named shibboleth.authn.SAML.discoveryFunction can be defined (using global.xml is fine) to produce the entityID of the IdP to use.
If some form of user interface is required to perform discovery, this must be achieved by implementing that in form of a compliant Discovery service (the standard protocol is based on simple redirects, so is readily implementable).
The SAML metadata describing the IdP you are proxying to is akin to the metadata that would drive any typical Shibboleth SP, and (apart from testing) should of course either be locally managed, or be refreshably-sourced from a trusted third-party with appropriate constraints on validity window, signature validation, and so forth applied.
Metadata representing the SP "half" of the Shibboleth IdP proxy (which you may need to give to the upstream IdP(s)) is of course also standard:
The IdP's entityID is presumed to be the same one applying to normal outbound use, but can be overridden if required (via the
issuerproperty on a https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199508044 bean).The
<AssertionConsumerService>for the IdP-acting-as-SP supports only the HTTP-POST binding and is located at the path "/idp/profile/Authn/SAML2/POST/SSO".Encryption is fully supported; you may not have bothered doing anything with the existing encryption key generated at install time but it will be used by default to decrypt incoming SAML and its certificate would need to be published in the metadata you give to the proxied IdP. Of course you are free not to do this and accept plaintext assertions.
If you wish to sign requests, you would also need to include the IdP’s usual signing certificate. Note that the primary use case for this is logout, but the proxying support doesn't include any logout integration at present. If logout is making fire, logout and proxying together is quantum physics.
A Note About Entra/Azure
Apparently Microsoft’s implementation enforces the underlying schema rule in SAML that the <RequesterID> element contains an actual URI. The IdP will populate this element with the identity of the downstream SP for which it is proxying authentication, and if it doesn’t happen to match Microsoft’s almost-certainly inexact determination about what constitutes a legal value, they reject it. If you’re proxying to it, you may need to set the SSO ignoreScoping profile configuration property to skip the creation of the entire <Scoping> element in the request.
It is notable that Azure happily allows the actual entityID of the SPs it connects to to contain any string value, despite that being unsafe, insecure, and of much greater consequence than the <RequesterID> element.
Post-Processing
The bulk of the configuration of this flow addresses the post-processing of the SAML Assertions that are returned in a successful response.
Authentication Time
By default, the AuthenticationResult created will be stamped with the AuthnInstant attribute supplied by the proxied IdP, which has implications on the policy you set for lifetime and timeout of these results. If you prefer to ignore that value and use the current time instead, you can set the SAML2.SSO profile bean’s isProxiedAuthnInstant setting to "false".
Attribute Extraction and Filtering
There are two sources of IdPAttribute decode/extraction possible:
The https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199510514
An optional function bean named shibboleth.authn.SAML.attributeExtractionStrategy
The first is a largely automated process to decode SAML Attributes based on standard rules, possibly supplemented by custom rules.
The second is an extension point for implementing any custom requirements you have, primarily for extracting data from the surrounding SAML Assertion or Response into information to operate on. The function is of Java type Function<ProfileRequestContext,Collection<IdPAttribute>> and may be defined in conf/global.xml. If all you need to consume are SAML<Attribute>(or in V5/2+<NameID>) elements, you should stick to the built-in mechanism and define new registry rules for decoding them if needed.
Once the results have been produced, the https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199501794 is applied to the results. This is a reversal of the usual filtering process of outbound data and operates with the proxying IdP itself as the "requester" and the proxied IdP as the "issuer", applying the Requester- and Issuer-based rules, respectively. It is also often desirable to apply "scope filtering" based on metadata when defining acceptance rules for scoped attributes.
If discriminating based on the issuer isn't sufficient, "Inbound" and "Outbound" policy rules are also provided for limiting policies based on the direction of the transaction.
No matter how you ultimately want to write these rules, it’s a good idea after testing to review your existing filtering policies to ensure you’re not allowing anything inbound you may not be intending to.
But also note that filtering in this sense does not extend to controlling what data might eventually be released to an SP; you can accept data here for whatever purpose without worrying about any leakage out later.
Example
An IdP proxying for a dedicated system with some discrete attributes might have a filter policy such as the following:
Example inbound filter policy
<AttributeFilterPolicy id="proxy">
<PolicyRequirementRule xsi:type="Issuer" value="https://upstream.example.org" />
<AttributeRule attributeID="givenName" permitAny="true" />
<AttributeRule attributeID="sn" permitAny="true" />
<AttributeRule attributeID="mail" permitAny="true" />
<AttributeRule attributeID="eduPersonPrincipalName">
<PermitValueRule xsi:type="ScopeMatchesShibMDScope" />
</AttributeRule>
</AttributeFilterPolicy>Subject Population
As with any other login flow, the product will be an AuthenticationResult containing a Java Subject with some number of Principal objects. Unlike many of the flows, the source of the Principals is somewhat more complex and flexible, and does not always lend itself to a trivial determination of a principal name during subject canonicalization.
The content of the Subject produced consists of the following:
Any IdPAttribute objects resulting from the extraction and filtering stage are wrapped in IdPAttributePrincipal objects.
If the incoming Assertion(s) contained a
<NameID>element, then a NameIDPrincipal is included that wraps that object directly.The incoming
<AuthnContext>element is used to construct one or more Principal objects that represent the nature of the authentication peformed. This is discussed further below, as it is subject to a lot of control/mapping if desired.A ProxyAuthenticationPrincipal is included that will contain the chain of proxied IdPs used, beginning with the immediate assertion issuer and including any additional upstream authorities identities in the
<AuthnStatement>, if any.
Most of that is automatic, but the processing of the SAML Authentication Context information is potentially complex because of the need to possibly translate the information received into a different form to align to the values the IdP uses internally and/or passes on to downstream SPs. By default, the information passes through a built-in translation function that relies on a map defined in conf/authn/authn-comparison.xml, discussed in the https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199505085topic. It's possible to override this translation behavior using the profile configuration (see Advanced Behavior below), but this is generally only required for interoperation with non-compliant SAML software.
Subject Canonicalization
As with all login flows, there is a requirement to process the AuthenticationResult into a normalized/simple principal name but because of the more complex nature of the resulting Subject, this isn't as trivial to do as with some other methods. Much as with the X.509 flow, there is no standard "username" to rely on and the system requires more explicit configuration to know what to do. Generally, either the attribute or SAML2ProxyTransform c14n flows are used, depending on whether the source of the principal name is based on a SAML Attribute or NameID, respectively.
With V5.2+, you can generally ignore the latter option in favor of defining a decoding rule for the <NameID> Format to turn it directly into an IdPAttribute and just use the former. We may deprecate the latter feature at some point simply due to the additional complexity involved.
In the former (attribute) case, the result can be pulled directly from the upstream IdP or actually come from the https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199502864, so there's a lot of flexibility in what to return, but simple passthrough or transform of a SAML <Attribute> (or with V5.2+ a <NameID>) is easy to express. An example below demonstrates this approach.
Note that a common use case is likely to be importing an opaque identifier such as one of the new Subject ID Attributes. While it's possible to directly expose such a value as the principal name, it is probably the case that a lot of mature proxy deployments would be expected to store and map that value to something of their own. That is not exactly a built-in feature at this point, but the most viable path to such a feature at present is probably to leverage a custom post-authentication interceptor that might detect an unlinked value and provide the user interface necessary to establish and store the linking information so that subsequent logins can retrieve the mapping from a typical directory or data source. Such an approach is beyond the scope of the documentation at this point.
Attribute-Sourced C14N Example
Note that this example assumes that the only use of this c14n feature is for this proxying use case. If you have a more complex scenario in which there are local authentication methods used as well and you use this feature for those, it gets more complex to combine them without breaking things, so take that into consideration. (This complexity is also reduced with V5.2+ as outlined in the https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199505212topic.)
Let's say you have an IdP supplying a standard eduPersonPrincipalName SAML <Attribute>to you and you want to build the principal name directly from that.
Assuming things are set up in a default manner, there's already a rule in the https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199510514 defined to map the SAML <Attribute>named "urn:oid:1.3.6.1.4.1.5923.1.1.1.6" into a scoped IdPAttribute with the ID of "eduPersonPrincipalName".
As noted in the attribute filtering and extraction section above, the IdP won't ingest the attribute to be used in this process unless it's also allowed to pass through the attribute filter configuration. So, an attribute filter policy must be added to attribute-filter.xml that maps the IdPAttribute to be used as an identifier, eduPersonPrincipalName in this example, from the incoming assertion:
Example inbound filter policy
<AttributeFilterPolicy id="proxy">
<PolicyRequirementRule xsi:type="Issuer" value="https://upstream.example.org" />
<AttributeRule attributeID="eduPersonPrincipalName">
<PermitValueRule xsi:type="ScopeMatchesShibMDScope" />
</AttributeRule>
</AttributeFilterPolicy>Then, configure the attribute-sourced post-login c14n flow by pointing it at "eduPersonPrincipalName" as a source. The properties to enable this are commented out in conf/c14n/subject-c14n.properties and are noted below.
Directing the IdP to use the c14n flow will depend on version.
Finally:
conf/c14n/subject-c14n.properties
idp.c14n.attribute.attributeSourceIds = eduPersonPrincipalName
# Allows direct use of attributes via SAML proxy authn, bypasses resolver
idp.c14n.attribute.resolveFromSubject = true
idp.c14n.attribute.resolutionCondition = shibboleth.Conditions.FALSEThe same general approach demonstrated above works for any IdPAttribute you can map in from the response.
The last property there is important, as it bypasses the actual running of the Attribute Resolver unnecessarily in order to simply pull in a decoded IdPAttribute from the upstream IdP.
Attribute Resolution
Finally, many proxying scenarios will often require some form of attribute pass-through or manipulation of data provided by the proxy as outgoing information. As a shorthand, the https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199504610 can be applied to produce internal or even auto-exported attributes within the https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199502864, and they can be used directly or leveraged as inputs to other attribute definitions or data connectors.
Advanced Behavior
Customizing the flow's behavior using profile configuration options is simple in practice, though may be a bit counter-intuitive: you treat the proxied Identity Provider as a "relying party" and leverage the usual mechanisms in conf/relying-party.xml to alter behavor using the SAML2.SSO profile configuration bean. That is, the same way you customize the behavior of SAML 2.0 SSO for SPs is also used to customize some of the behavior for SAML 2.0 IdPs.
Since SAML 2.0 SSO is normally one of the default supported profiles, the general use of this flow is enabled simply by providing IdP metadata and invoking the flow. If you were to remove the "SAML2.SSO" bean from the DefaultRelyingParty's profileConfigurations property, the flow would fail to operate. In the same way, creating an override that applies to the proxied IdP with a customized bean will adjust the behavior of the profile in a variety of ways that mirror the use of the settings in the opposite direction.
Not all the settings actually apply to the proxying use case, but most of them have an analog interpretation and some are specific to proxying.
There are also some defaults that act somewhat differently depending on which use case is involved. The forceAuthn setting for example can be turned on normally to forcibly apply that option to the request issued, but the default is not actually false when proxying but rather passes through whatever setting was in effect from the original request from the SP.
Similarly, the defaultAuthenticationMethods and authnContextComparison properties default to nothing normally but when proxying cause the original SP's requirements to be expressed to the proxied IdP in possibly translated form. There is some more general material on the mapping of <AuthnContext> requirements in the parent topic, under Advanced Topics → Proxying → Authentication Type Mapping.
Note that as with all other profile configuration behavior, it's possible to leverage metadata extension tags to drive these settings.
Reference
More Examples
These are non-curated examples from contributors to supplement the core documentation.
https://shibboleth.atlassian.net/wiki/spaces/KB/pages/1459979597
https://shibboleth.atlassian.net/wiki/spaces/KB/pages/2783936889