Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

In this case the bean definition for the activation condition (MyCondition above) should be included in a suitable native spring file.

Simple conditions, and those requiring to be reloadable, should be placed in a standalone file loaded via conf/services.xml.

Bean defintion for selection by

...

Relying Party ID
Expand
Code Block
languagexml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    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">
 
    <bean id="ExampleOrgPredicate" parent="shibboleth.Conditions.RelyingPartyId" c:candidate="https://sp.example.com/shibboleth" />
</beans>

This

...

file must be supplied to the appropriate resource list in conf/services.xml.  For instance for the Attribute Resolver

...

:

Including an extra file in services.xml
Code Block
languagexml
<util:list id ="shibboleth.AttributeResolverResources">
    <value>${idp.home}/conf/attribute-resolver.xml</value>
    <value>${idp.home}/conf/THE_NEW_FILE.xml</value>
</util:list>

Complex beans that will never need to be reloaded can be put in conf/global.xml (or a file imported into it).

Examples

If you develop useful examples, please consider adding them to this page. The examples below are not fully tested in a few cases, so please report any problems using them to the mailing list or make corrections as you find them.

...

Specific Relying Parties by Name
Expand
Code Block
languagexml
<!-- Single SP -->
<bean id="MyCondition" parent="shibboleth.Conditions.RelyingPartyId"
  c:candidate="https://sp.example.com/shibboleth" />

<!-- Multiple SPs, expression -->
<bean id="MyCondition" parent="shibboleth.Conditions.RelyingPartyId"
  
c:candidates="#{{'https://sp.example.com/shibboleth', 'https://another.example.com/shibboleth'}}" />

<!-- Multiple SPs, list bean -->
<bean id="MyCondition" parent="shibboleth.Conditions.RelyingPartyId">
  <constructor-arg name="candidates">
    
<list>
      <value>https://sp.example.com/shibboleth</value>

      <value>https://another.example.com/shibboleth</value>
    </list>
  </constructor-arg>
</bean>

A more advanced option supported by the same parent bean is the ability to plug-in an arbitrary condition to run against the relying party name. The input to such a condition is a String rather than the ProfileRequestContext.

Test a Regular Expression
Expand
Code Block
languagexml
<!-- Test a regular expression against the Relying Party name -->
<bean id="MyCondition" parent="shibboleth.Conditions.RelyingPartyId">
  
<constructor-arg>
    <bean class="com.google.common.base.Predicates" factory-method="containsPattern"

      c:pattern="^https://[^/]+\.example\.com/shibboleth$" />
  </constructor-arg>
</bean>

You can also write a script (Javascript being the default language):

Javascript Example
Expand
Code Block
languagexml
<!-- A script that checks a Relying Party name -->
<bean id="MyCondition" parent="shibboleth.Conditions.Scripted" factory-method="inlineScript">
  <constructor-arg>
<value>
    <value>
    <![CDATA[
      "use strict";
var
 
result
 
=
 
false;
   var result = false;

      // an implementation of Predicate<ProfileRequestContext>

      
// The IdP environment provides two variables "profileContext" and "custom".  
      
//     profileContext  is of type org.opensaml.profile.context.ProfileRequestContext
      
//     custom          is whatever you injected 
      // 
// The
The value of the last statement in this function is the reurn value

      
var id = "https://sp.example.com/shibboleth";  // an entityID
      
      // specify the child context of the root ProfileRequestContext
      if (profileContext!== null) {
    
var subcontextClass
      // check the entityID of the relying party
          var subcontext = profileContext.getSubcontext("net.shibboleth.idp.profile.context.RelyingPartyContext");
          if (subcontext 
var subcontext;
!== null) {
            
//
result 
check the parameter if (profileContext!== null) {
= subcontext.getRelyingPartyId().equals(id);
          }
     
//
 
check
}
the
 
entityID
 
of
 
the
 
relying
 
party
 result;
    ]]>
    
subcontext = profileContext.getSubcontext(subcontextClass); if (subcontext !== null) { result = subcontext.getRelyingPartyId().equals(id); } } result; ]]> </value> </
</value>
  </constructor-arg>
</bean>

Finally, you can write Spring Expressions, sort of a more concise scripting format:

Spring Expression Example
Expand
Code Block
languagexml
<!-- A Spring Expression that checks a Relying Party name -->
<bean id="MyCondition" parent="shibboleth.Conditions.Expression">
  
<constructor-arg>
 
<value>
   <value>
    #profileContext.getSubcontext(T(net.shibboleth.idp.profile.context.RelyingPartyContext)).getRelyingPartyId().equals("https://sp.example.com/shibboleth"
)
)
    </value>
  </constructor-arg>
</bean>

Relying Parties By Group

In this context, grouping RPs is historically done by containing SAML metadata entities in <md:EntitiesDescriptor> elements, something common to aggregated files produced by many federations. This is more of a historical use case, because it's dangerous to use with aggregates you don't control. The containment model is very limiting and often doesn't mean what people think it does, so it's better to use the "tag" approach illustrated below.

...

Most use cases for this feature tend to be for relying party overrides, which are already supported separately. If you need to use this kind of condition elsewhere, you can reuse the same code with this example:

Relying Parties By Group
Expand
Code Block
languagexml
<!-- One group -->
<bean id="MyCondition" parent="shibboleth.Conditions.EntityDescriptor">
 
 <constructor-arg name="pred">
    <bean class="org.opensaml.saml.common.profile.logic.EntityGroupNamePredicate"
      c:_0="nameofgroup" />
  </constructor-arg>
</bean>

<!-- Multiple groups, expression -->
<bean id="MyCondition" parent="shibboleth.Conditions.EntityDescriptor">
  
<constructor-arg name="pred">
 
   <bean class="org.opensaml.saml.common.profile.logic.EntityGroupNamePredicate"
      c:_0="#{{'group1', 'group2'}}" />
  
</constructor-arg>
</bean>

<!-- Multiple groups, list bean -->
<bean id="MyCondition" parent="shibboleth.Conditions.EntityDescriptor">
  
<constructor-arg name="pred">
    <bean class="org.opensaml.saml.common.profile.logic.EntityGroupNamePredicate">
      <constructor-arg>
<list> <value>group1</value> <value>group2</value> </list>

        <list>
          <value>group1</value>
          <value>group2</value>
        </list>
      </constructor-arg>
    
</bean>
 
 </constructor-arg>
</bean>

Relying Parties By Tag

The "modern" approach to attaching policy to relying parties is to leverage so-called tags, which refers to a metadata extension called an "Entity Attribute", a SAML attribute embedded in a system's metadata that is about the system rather than an individual user. Entity attributes have a variety of use cases, essentially anything one can think of saying about a system, and they're more flexible than groups because they can be attached directly to the entity's metadata regardless of where it's published. If you will, this is the equivalent of an LDAP "memberOf" attribute as opposed to a directory object that contains all the members of a group.

Most use cases for this feature tend to be for relying party overrides, which are already supported separately. If you need to use this kind of condition elsewhere, you can reuse the same code with this example:

Relying Party By Tag
Expand
Code Block
languagexml
<!-- Tag condition -->
<bean id="MyCondition" parent="shibboleth.Conditions.EntityDescriptor">
  <constructor-arg name="pred">
  
  <bean class="org.opensaml.saml.common.profile.logic.EntityAttributesPredicate">
      <constructor-arg>
        
<list>
<list>
          <bean class="org.opensaml.saml.common.profile.logic.EntityAttributesPredicate.Candidate"
          c:name="http://macedir.org/entity-category"

      
    
p:values="http://refeds.org/category/research-and-scholarship" />

        </list>
      </constructor-arg>
 <

    </bean>
 
 </constructor-arg>
</bean>

Client Address Ranges

Some components may be sensitive to the address of the client, perhaps to distinguish users running on an enterprise network vs. working remotely. A condition class has been created to make this check simple using CIDR masks. Note that a servlet request bean declared by the Shibboleth software MUST be injected into any bean that needs access to the current request (the same is true of the servlet response in other cases).

...

Code Block
languagexml
<bean id="MyCondition" class="org.opensaml.profile.logic.IPRangePredicate"
	  p:httpServletRequest-ref="shibboleth.HttpServletRequest"
	  p:ranges="#{ '192.168.1.0/24', '192.168.2.0/28' }" />

Attribute Checking

Some components may need to check for the presence (or absence) of a particular attribute or value for a user. A basic condition is provided for this purpose, or may be a useful code example to follow to implement something more complex.

...

Attribute Checking Examples
Expand
Code Block
languagexml
<!-- Check for a particular entitlement -->
<bean class="net.shibboleth.idp.profile.logic.SimpleAttributePredicate" p:useUnfilteredAttributes="true">
  <property name="attributeValueMap">
    
<map>
      <entry key="entitlement">
<list>

        <list>
          <value>urn:mace:dir:entitlement:common-lib-terms</value>

        </list>
      </entry>
    </map>
  
</property>
</bean>

<!-- Check that an eduPersonPrincipalName exists -->
<bean class="net.shibboleth.idp.profile.logic.SimpleAttributePredicate">
  
<property name="attributeValueMap">
<map>
    <map>
      <entry key="eppn">
<list>

        <list>
          <value>*</value>
        </list>
      </entry>
   
 </map>
  </property>
</bean>

Compound Boolean Conditions

...

Either of Two Relying Parties
Expand
Code Block
languagexml
<!-- An OR used to check for one of two relying parties -->
<bean id="MyCondition" parent="shibboleth.Conditions.OR">
 
 <constructor-arg>
    
<list>

      <bean parent="shibboleth.Conditions.RelyingPartyId" c:candidate="https://sp.example.com/shibboleth" />
      <bean parent="shibboleth.Conditions.RelyingPartyId" c:candidate="https://another.example.com/shibboleth" />
 
   </list>
  
</constructor-arg>
</bean>

The second example demonstrates a compound condition that checks a specific SP AND for a particular client network range.

Specific Relying Party AND Client Address Range
Expand
Code Block
languagexml
<!-- An AND checking for both an SP and a network address -->
<bean id="MyCondition" parent="shibboleth.Conditions.AND">
  <constructor-arg>
    <bean parent="shibboleth.Conditions.RelyingPartyId" c:candidate="https://sp.example.com/shibboleth" />
  </constructor-arg>
  <constructor-arg>
    <bean class="org.opensaml.profile.logic.IPRangePredicate"

      p:httpServletRequest-ref="shibboleth.HttpServletRequest"

      p:ranges="192.168.1.0/24" />
 
 </constructor-arg>
</bean>

Finally, a simple NOT example checking for any SP except for one:

NOT a Specific Relying Party
Expand
Code Block
languagexml
<!-- Any SP except for one -->
<bean id="MyCondition" parent="shibboleth.Conditions.NOT">
  <constructor-arg>
    <bean parent="shibboleth.Conditions.RelyingPartyId" c:candidate="https://sp.example.com/shibboleth" />
  
</constructor-arg>
</bean>