RelyingPartyConfiguration

File(s): conf/relying-party.xml, conf/idp.properties
Format: Native Spring

Overview

The relying-party.xml file is used to specify the functional features (SAML and otherwise) you want the IdP to support (these are termed "profiles"), and to customize IdP or profile settings based on the identity, or a few other characteristics, of a relying party service.

You can modify this file to:

  • control which profiles are supported for particular partners (or for anonymous requests)

  • alter default profile or global settings

  • define and attach custom security configurations at various levels, such as:

    • turning off encryption of assertions and other content

    • changing which layer signing is performed (responses vs. assertions)

    •  supporting multiple signing credentials

    • customizing algorithms

The goal of any deployment is to reduce the number of customizations used, so the ideal is to rarely have to modify this configuration. Further, there are more modern techniques that allow many or most uses of this file to be replaced by MetadataDrivenConfiguration; that is, instead of creating explicit rules in this file, it's usually cleaner in the long run to add information to SP metadata to effect the change desired. Over time, it becomes easier to get a feel for when it's easier to use metadata and when it's easier to use overrides.

General Configuration

While the native Spring syntax can ultimately be used to wire up any beans you choose to define, we have abstracted this to some degree by making use of conventions, parent beans, and pre-defined bean names to limit the amount of XML needed to make useful changes.

The absolute rule is that the file MUST contain three named beans:

  • shibboleth.UnverifiedRelyingParty

  • shibboleth.DefaultRelyingParty

  • shibboleth.RelyingPartyOverrides

All three are defined for you by default.

The first two must define beans that derive from the RelyingPartyConfiguration class, but this is automatically done by inheriting (via the parent attribute) from the bean named RelyingParty.

The "unverified" RP bean controls how to handle requests from peers with no metadata or other mechanism in place to authenticate/verify the request. By default, no profiles are enabled, signified by the empty profileConfigurations list.

The "default" RP bean applies to requests from peers that do not fit the conditions attached to any overrides, and are thus handled with default settings. By default, this relies on a variety of built-in settings, and activates a number of the usual profiles, though the exact list may vary over time with particular releases (things that used to be common may become rare).

The last bean is a List<RelyingPartyConfiguration> for any overrides. Those beans will generally be of special types that determine their applicability, or will generically contain an activationCondition property that determines whether one applies to a request or not.

The first applicable override bean is used, and there is no merging of settings between any of the beans.

Overrides

Overrides allow for arbitrary conditions to be evaluated to assign behavior to a request. In the general case these conditions can be complex scripts or Java code.

To simplify this in the most common scenarios, we have included additional parent beans that can be inherited from to more easily express these conditions. Right now, we have these built-in helpers:

  • RelyingPartyByName

  • RelyingPartyByGroup

  • RelyingPartyByEntitiesDescriptor 4.1

  • RelyingPartyByTag

  • RelyingPartyByMappedTag

Examples

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <!-- Example matching one SP --> <bean parent="RelyingPartyByName" c:relyingPartyIds="https://sp.example.org/sp"> <property name="profileConfigurations"> <list> <!-- Your refs or beans here. --> </list> </property> </bean> <!-- Example matching two SPs --> <bean parent="RelyingPartyByName" c:relyingPartyIds="#{{'https://sp.example.org/sp', 'https://another.example.org/sp'}}"> <property name="profileConfigurations"> <list> <!-- Your refs or beans here. --> </list> </property> </bean> <!-- Example matching three (or more) SPs --> <bean parent="RelyingPartyByName"> <constructor-arg name="relyingPartyIds"> <list> <value>https://sp.example.org/sp</value> <value>https://another.example.org/sp</value> <value>https://still.another.example.org/sp</value> </list> </constructor-arg> <property name="profileConfigurations"> <list> <!-- Your refs or beans here. --> </list> </property> </bean

(Note that the second example above uses a Spring Expression Language inline list. This can get arbitrarily long, so the third example shows this in a more readable syntax for longer lists.)

The following example notwithstanding, it's not advisable to create policy based on groups because those hierarchies are very dependent on metadata aggregation and publishing approaches that are much less common today.

1 2 3 4 5 6 7 <bean parent="RelyingPartyByGroup" c:groupNames="urn:mace:incommon"> <property name="profileConfigurations"> <list> <!-- Your refs or beans here. --> </list> </property> </bean>

There is also support for group matching based on a SAML metadata feature called an <AffiliationDescriptor>, and you are able to create locally (or even remotely) expressed group memberships using that technique, by supplying supplemental metadata to the system. If you want to optimize by ignoring the possibility of  <AffiliationDescriptor> use, the RelyingPartyByEntitiesDescriptor bean has been added (as of V4.1) to bypass that step and suppress some logging that shows up during the affiliation lookup.

An alternative grouping strategy is based on <EntityAttributes> metadata extension tags. The tag-based approach is a generally recommended way of doing simple overrides that might apply to a large number of systems, and is a bridge between the "explicit" syntax and the more generic MetadataDrivenConfiguration approach.

1 2 3 4 5 6 7 8 9 10 11 12 13 <bean parent="RelyingPartyByTag"> <constructor-arg name="candidates"> <list> <bean parent="TagCandidate" c:name="http://macedir.org/entity-category" p:values="http://refeds.org/category/research-and-scholarship"/> </list> </constructor-arg> <property name="profileConfigurations"> <list> <!-- Your refs or beans here. --> </list> </property> </bean>

In addition to the original bean, the RelyingPartyByMappedTag bean allows you to optimize tag-based overrides by relying on the decoding of tags in the metadata into internal IdPAttribute objects via the AttributeRegistryConfiguration. Even without dedicated rules, the system can auto-decode URI-named SAML Attribute extensions into IdPAttributes with a corresponding name "as is", so generally the mapped variant should work the same way and will be faster.

Finally, the most general example involves defining your own bean and a custom condition. An example using a regular expression:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <bean id="exampleOrgRegex" class="java.util.regex.Pattern" factory-method="compile" c:_0="^https://sp[\d].example\.org/shibboleth$" /> <bean id="exampleOrgRegexPredicate" class="com.google.common.base.Predicates" factory-method="contains" c:_0-ref="exampleOrgRegex" /> <bean id="custom.RelyingPartyCondition" class="net.shibboleth.idp.profile.logic.RelyingPartyIdPredicate" c:_0-ref="exampleOrgRegexPredicate" /> <bean id="CustomRelyingParty" parent="RelyingParty" p:activationCondition-ref="custom.RelyingPartyCondition"> <property name="profileConfigurations"> <list> <!-- Your refs or beans here. --> </list> </property> </bean>

Multiple Overrides

If more than one override is defined, then it is possible for the activation conditions of multiple overrides to be satisfied by a request. Overrides have "first one wins" match semantics whose ordering is determined by their position in the shibboleth.RelyingPartyOverrides list bean. This leads to a rule of thumb for overrides: more general matches (i.e. by group) should be placed after more specific matches (i.e. by name).

The first override with an ActivationCondition that returns true will be in effect. Multiple matching overrides are not merged or combined in any way. However, it's possible to combine different "dimensions" of conditions by using dynamically-derived profile settings, a feature discussed in the next section and in the MetadataDrivenConfiguration topic.

Profile Configuration

Every relying party configuration (default or override) has a profileConfigurations property whose value is a list of ProfileConfiguration beans that determine which profiles can be used. Any profile not explicitly listed will be disabled and requests for it will fail internally with an error.

Profiles are activated within relying party configurations in most cases by referencing beans defined within the system that apply the default settings for each profile. This wouldn't apply to custom profiles defined in extensions, but it does apply to the built-in feature set. We've pre-defined beans for the built-in profiles as follows:

They ones that are active by default are included in the shibboleth.DefaultRelyingParty bean's profileConfigurations property, by reference. You can turn them on or off using comments or by deleting them.

Additional profile beans are available when the CAS module is enabled; see CasProtocolConfiguration.

As with all relying party settings, an override does not inherit the profiles enabled by default. An override essentially turns everything off unless its own profileConfigurations property enables it.

To statically override a default profile option, you can replace a <ref> element pointing to a profile with a new bean definition like so:

1 <bean parent="SAML2.SSO" p:nameIDFormatPrecedence="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" />

The parent attribute lets you pull in the pre-defined bean definition for a profile and just override what you want to. You can mix these beans with <ref> elements that rely on default behavior with other profiles.

In many, if not most cases, it's a better idea to look into MetadataDrivenConfiguration then to explore this feature. This is the low-level feature that makes metadata-driven settings possible but using metadata is usually more elegant and the system does all the fancy wiring for you.

In the most advanced cases, most all profile settings can be derived at runtime using Java functions or scripts, termed "lookup strategies", instead of declaring them statically. This can be done for default or overridden relying party configurations, and provides a powerful way of combining different kinds of rules.

This is a useful trick to use if you want to apply "cross-cutting" conditions to get around the limitation that overrides don't get merged. For example, consider the following use cases:

  • You want to enable consent for attribute release for a specific set of relying parties.

  • You want to downgrade to the use of SHA-1 for a specific set of relying parties.

Of course, if these two sets don't overlap, and you have nothing else unusual to specify, you could create two overrides for each set individually. But what if the two sets overlap, with some relying parties in one, some in the other, and some in both? Now you need three overrides. Now consider that a third set requires an additional non-default setting and overlaps with some of the first two sets. The number of overrides will get out of hand quickly and start to get very confusing to manage.

As an example, let's tackle the cases above by using scripts to derive the settings involved. This can potentially be done with no overrides at all, as below, though that's a matter of style.

Use of scripts to derive profile settings
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 <!-- Whether to run attribute release interceptor. --> <bean id="InterceptorScript" parent="shibboleth.ContextFunctions.Scripted" factory-method="inlineScript"> <constructor-arg> <value> <![CDATA[ interceptors = null; rpid = ""; rpCtx = input.getSubcontext("net.shibboleth.idp.profile.context.RelyingPartyContext"); if (rpCtx != null) { rpid = rpCtx.getRelyingPartyId(); } if (rpid.equals("https://sp1.example.org/sp") || rpid.equals("https://sp2.example.org/sp") || rpid.equals("https://sp3.example.org/sp")) { listType = Java.type("java.util.ArrayList"); interceptors = new listType(1); interceptors.add("attribute-release"); } interceptors; ]]> </value> </constructor-arg> </bean> <!-- Map of security configurations for use by next script. --> <util:map id="SecurityConfigMap"> <entry key="SHA2" value-ref="shibboleth.DefaultSecurityConfiguration"/> <entry key="SHA1" value-ref="shibboleth.SecurityConfiguration.SHA1" /> </util:map> <!-- Whether to use SHA-1. --> <bean id="SecurityConfigScript" parent="shibboleth.ContextFunctions.Scripted" factory-method="inlineScript" p:customObject-ref="SecurityConfigMap"> <constructor-arg> <value> <![CDATA[ rpid = ""; rpCtx = input.getSubcontext("net.shibboleth.idp.profile.context.RelyingPartyContext"); if (rpCtx != null) { rpid = rpCtx.getRelyingPartyId(); } securityConfig = custom["SHA2"]; if (rpid.equals("https://sp2.example.org/sp") || rpid.equals("https://sp3.example.org/sp") || rpid.equals("https://sp4.example.org/sp")) { securityConfig = custom["SHA1"]; } securityConfig; ]]> </value> </constructor-arg> </bean> <!-- Apply the scripts to derive settings. --> <bean id="shibboleth.DefaultRelyingParty" parent="RelyingParty"> <property name="profileConfigurations"> <list> <bean parent="Shibboleth.SSO" p:postAuthenticationFlowsLookupStrategy-ref="InterceptorScript" p:securityConfigurationLookupStrategy-ref="SecurityConfigScript" /> <bean parent="SAML2.SSO" p:postAuthenticationFlowsLookupStrategy-ref="InterceptorScript" p:securityConfigurationLookupStrategy-ref="SecurityConfigScript" /> <ref bean="SAML2.ECP" p:securityConfigurationLookupStrategy-ref="SecurityConfigScript" /> <ref bean="SAML2.Logout" p:securityConfigurationLookupStrategy-ref="SecurityConfigScript" /> </list> </property> </bean>

Obviously the example above is somewhat contrived. It's longer than just creating three overrides, but it illustrates the general idea and once you get comfortable using scripts, it isn't as bad as it looks. It's also possible to put scripts in separate files, which makes the XML much shorter.

This becomes much more powerful when combined with other techniques, particularly the use of tag-based conditions based on <EntityAttribute> extensions in SAML metadata, which can be applied by metadata registrars or locally using a metadata filter.

A built-in way of doing this is described in the MetadataDrivenConfiguration topic, and this is the generally-advisable means of handling complex configuration of behavior now.

If custom profile defaults are needed for several categories of relying party, it is helpful to define top-level profile beans and reference them in the relying parties instead of the system default beans. This approach reduces duplication and produces a more readable configuration. A concrete example is instructive: suppose that an IdP needs to declare custom NameID precedence for SSO profiles for the default relying party and several overrides. The following configuration excerpt demonstrates the approach applied to that case.

Custom Profile Default Beans Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 <bean id="Shibboleth.SSO.custom" parent="Shibboleth.SSO" p:nameIDFormatPrecedence="#{{ 'urn:mace:shibboleth:1.0:nameIdentifier', 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'}}" /> <bean id="SAML2.SSO.custom" parent="SAML2.SSO" p:nameIDFormatPrecedence="#{{ 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent', 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient', 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'}}" />   <bean id="shibboleth.DefaultRelyingParty" parent="RelyingParty"> <property name="profileConfigurations"> <util:list> <ref bean="Shibboleth.SSO.custom" /> <ref bean="SAML1.AttributeQuery" /> <ref bean="SAML1.ArtifactResolution" /> <ref bean="SAML2.SSO.custom" /> <ref bean="SAML2.ECP" /> <ref bean="SAML2.Logout" /> <ref bean="SAML2.AttributeQuery" /> <ref bean="SAML2.ArtifactResolution" /> </util:list> </property> </bean>   <util:list id="shibboleth.RelyingPartyOverrides"> <bean parent="RelyingPartyByName" c:relyingPartyIds="#{{'https://a.example.com/shibboleth', 'https://b.example.com/shibboleth'}}"> <property name="profileConfigurations"> <list> <bean parent="SAML2.SSO.custom" p:encryptAssertions="false" /> </list> </property> </bean> <bean parent="RelyingPartyByName" c:relyingPartyIds="#{{'https://x.example.com/shibboleth', 'https://y.example.com/shibboleth'}}"> <property name="profileConfigurations"> <list> <bean parent="Shibboleth.SSO.custom" p:signAssertions="true" p:signResponses="false" /> <bean parent="SAML2.SSO.custom" p:signAssertions="true" p:signResponses="false" /> </list> </property> </bean> </util:list>

 

Reference

Properties defined in idp.properties directly related to this configuration area follow:

Property

Type

Default

Function

Property

Type

Default

Function

idp.entityID

URI

None

The unique name of the IdP, used as the "issuer" in all SAML profiles

idp.artifact.enabled

Boolean

true

Whether to allow use of the SAML artifact bindings when sending messages

idp.artifact.secureChannel

Boolean

true

Whether preparation of messages to be communicated via SAML artifact should assume use of a secure channel (allowing signing and encryption to be skipped)

idp.artifact.endpointIndex              

Integer

2

Identifies the <ArtifactResolutionService> endpoint in SAML metadata associated with artifacts issued by a server node

idp.bindings.inMetadataOrder 4.1

Boolean

true

Controls whether the outbound binding selection is ordered by the SP's metadata or the IdP's preferred bindings; turn this off to leave artifact support on, but favor use of POST

Beans defined in relying-party.xml and related system configuration follow:

Bean ID

Type

Function

Bean ID

Type

Function

shibboleth.UnverifiedRelyingParty

RelyingPartyConfiguration

Configures IdP behavior for unauthenticated/unverifiable requests

shibboleth.DefaultRelyingParty

RelyingPartyConfiguration

Configures default IdP behavior for authenticated/verified requests

shibboleth.RelyingPartyOverrides

List<RelyingPartyConfiguration>

Configures non-default IdP behavior for requests that meet activation conditions attached to overrides

RelyingParty

RelyingPartyConfiguration

A template bean for use in defining RelyingParty overrides by hand

RelyingPartyByName

RelyingPartyConfiguration

A template bean for defining RelyingParty overrides based on matching by name

RelyingPartyByGroup

RelyingPartyConfiguration

A template bean for defining RelyingParty overrides based on matching by <EntitiesDescriptor> groups or SAML metadata-based <AffiliationDescriptor> groups

RelyingPartyByEntitiesDescriptor 4.1

RelyingPartyConfiguration

A template bean for defining RelyingParty overrides based on matching by <EntitiesDescriptor> groups only

RelyingPartyByTag

RelyingPartyConfiguration

A template bean for defining RelyingParty overrides based on matching <EntityAttributes> extension content

RelyingPartyByMappedTag

RelyingPartyConfiguration

A template bean for defining RelyingParty overrides based on matching <EntityAttributes> extension content that has been mapped via the AttributeRegistryConfiguration

TagCandidate

EntityAttributesPredicate.Candidate

A template bean for defining EntityAttribute matching rules for injection into beans based on RelyingPartyByTag

Shibboleth.SSO

BrowserSSOProfileConfiguration

Default configuration for SAML 1.1 SSO profile

SAML1.AttributeQuery

AttributeQueryProfileConfiguration

Default configuration for SAML 1.1 Attribute Query profile

SAML1.ArtifactResolution

ArtifactResolutionProfileConfiguration

Default configuration for SAML 1.1 Artifact Resolution profile

SAML2.SSO

BrowserSSOProfileConfiguration

Default configuration for SAML 2.0 SSO profile

SAML2.ECP

ECPProfileConfiguration

Default configuration for SAML 2.0 Enhanced Client/Proxy profile

SAML2.Logout

SingleLogoutProfileConfiguration

Default configuration for SAML 2.0 Single Logout profile

SAML2.AttributeQuery

AttributeQueryProfileConfiguration

Default configuration for SAML 2.0 Attribute Query profile

SAML2.ArtifactResolution

ArtifactResolutionProfileConfiguration

Default configuration for SAML 2.0 Artifact Resolution profile

Liberty.SSOS

SSOSProfileConfiguration

Default configuration for Liberty ID-WSF Delegated SSO profile

CAS.LoginConfiguration

LoginConfiguration

Default configuration for CAS login prototol

CAS.ProxyConfiguration

ProxyConfiguration

Default configuration for CAS proxy login protocol

CAS.ValidateConfiguration

ValidateConfiguration

Default configuration for CAS ticket validation protocol

shibboleth.DefaultArtifactConfiguration

BasicSAMLArtifactConfiguration

Default configuration for SAML Artifact usage, injected into artifact-supporting SAML profile beans

Without stepping fully into the SecurityConfiguration topic, the following defaults are used when enabling individual profiles. In addition, an appropriate "security policy" flow is enabled during request processing to enforce appropriate security guarantees.

  • All SAML Profiles

    • includeConditionsNotBefore = true

    • assertionLifetime = PT5M

    • signedRequestsPredicate = alwaysFalse

    • signAssertionsPredicate = alwaysFalse

  • Shibboleth.SSO

    • includeAttributeStatement = false

    • signResponsesPredicate = alwaysTrue

    • use of type 1 SAML artifacts where required

  • SAML1.AttributeQuery

  • SAML1.ArtifactResolution

    • signResponsesPredicate = if TLS isn't used or port 443 is used

  • SAML2.SSO

  • SAML2.ECP

    • includeAttributeStatement = true

    • skipEndpointValidationWhenSigned = false

    • maximumSPSessionLifetime = 0

    • signResponsesPredicate = alwaysTrue

    • encryptAssertionsPredicate = alwaysTrue

    • encryptNameIDsPredicate = alwaysFalse

    • encryptAttributesPredicate = alwaysFalse

    • use of type 4 SAML artifacts where required with an endpoint index of %{idp.artifact.endpointIndex:2}

  • SAML2.Logout

    • signRequestsPredicate = alwaysTrue on front channel, if TLS isn't used or port 443 is used on back channel

    • signResponsesPredicate = alwaysTrue on front channel, if TLS isn't used or port 443 is used on back channel

    • encryptNameIDsPredicate = alwaysTrue on front channel, if TLS isn't used or port 443 is used on back channel

    • use of type 4 SAML artifacts where required with an endpoint index of %{idp.artifact.endpointIndex:2}

  • SAML2.AttributeQuery

  • SAML2.ArtifactResolution

    • signResponsesPredicate = if TLS isn't used or port 443 is used

    • encryptAssertionsPredicate = if TLS isn't used or port 443 is used