[java-identity-provider] 03/08: Work on SAML 2 artifact decoder SOAP client pipeline and wiring.

Brent Putman putmanb at georgetown.edu
Fri Sep 21 22:49:08 EDT 2018


This is an automated email from the git hooks/post-receive script.

putmanb pushed a commit to branch master
in repository java-identity-provider.

View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=ff930dce36e00d2376784e008495849ae9e6638e

commit ff930dce36e00d2376784e008495849ae9e6638e
Author: Brent Putman <putmanb at georgetown.edu>
AuthorDate: Thu May 17 18:24:48 2018 -0400

    Work on SAML 2 artifact decoder SOAP client pipeline and wiring.
---
 .../main/resources/system/conf/global-system.xml   |   3 +
 .../main/resources/system/conf/services-system.xml |   4 +
 .../src/main/resources/system/conf/soap-client.xml | 164 +++++++++++++++++++++
 .../src/main/resources/system/conf/utilities.xml   |  10 ++
 .../system/flows/saml/saml-abstract-beans.xml      |   7 +
 .../system/flows/saml/saml2/sso-artifact-beans.xml |   9 +-
 ...pClientSecurityConfigurationLookupFunction.java |  84 +++++++++++
 ...ignatureSigningConfigurationLookupFunction.java |  84 +++++++++++
 ...atureValidationConfigurationLookupFunction.java |  84 +++++++++++
 .../AbstractRelyingPartyLookupFunction.java        |  79 ++++++++++
 .../messaging/impl/SelectProfileConfiguration.java | 158 ++++++++++++++++++++
 .../impl/SelectRelyingPartyConfiguration.java      | 149 +++++++++++++++++++
 .../impl/CriteriaSelfEntityIDResolver.java         | 121 +++++++++++++++
 .../InitializeRelyingPartyContextFromSAMLPeer.java | 139 +++++++++++++++++
 14 files changed, 1091 insertions(+), 4 deletions(-)

diff --git a/idp-conf/src/main/resources/system/conf/global-system.xml b/idp-conf/src/main/resources/system/conf/global-system.xml
index f454db4..dafb418 100644
--- a/idp-conf/src/main/resources/system/conf/global-system.xml
+++ b/idp-conf/src/main/resources/system/conf/global-system.xml
@@ -49,6 +49,7 @@
     <import resource="cas-protocol-system.xml" />
     <import resource="general-admin-system.xml" />
     <import resource="utilities.xml" />
+    <import resource="soap-client.xml" />
 
     <bean id="systemPrereqs" class="org.springframework.beans.factory.config.MethodInvokingBean"
             p:targetObject-ref="systemProperties" p:targetMethod="putAll">
@@ -324,6 +325,8 @@
         c:resolver-ref="shibboleth.MetadataCredentialResolver" />
     <bean id="shibboleth.ClientTLSValidationParametersResolver"
         class="org.opensaml.security.x509.tls.impl.BasicClientTLSValidationParametersResolver" />
+    <bean id="shibboleth.HttpClientSecurityParametersResolver"
+        class="org.opensaml.security.httpclient.impl.BasicHttpClientSecurityParametersResolver" />
 
     <!--
     The beans below are primarily used by trust engines in relying-party-system.xml, but also in the
diff --git a/idp-conf/src/main/resources/system/conf/services-system.xml b/idp-conf/src/main/resources/system/conf/services-system.xml
index 224a452..e6c8d3a 100644
--- a/idp-conf/src/main/resources/system/conf/services-system.xml
+++ b/idp-conf/src/main/resources/system/conf/services-system.xml
@@ -125,6 +125,10 @@
         class="net.shibboleth.idp.relyingparty.impl.ReloadingRelyingPartyConfigurationResolver"
         c:resolverService-ref="shibboleth.RelyingPartyResolverService" />
         
+    <bean id="shibboleth.CriteriaRelyingPartyConfigurationResolver" 
+        class="net.shibboleth.idp.relyingparty.impl.DelegatingCriteriaRelyingPartyConfigurationResolver"
+        p:delegate-ref="shibboleth.RelyingPartyConfigurationResolver" />
+        
     <bean id="shibboleth.MetadataResolver"
         class="net.shibboleth.idp.saml.metadata.impl.ReloadingRelyingPartyMetadataProvider"
         c:resolverService-ref="shibboleth.MetadataResolverService" />
diff --git a/idp-conf/src/main/resources/system/conf/soap-client.xml b/idp-conf/src/main/resources/system/conf/soap-client.xml
new file mode 100644
index 0000000..7b51feb
--- /dev/null
+++ b/idp-conf/src/main/resources/system/conf/soap-client.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:c="http://www.springframework.org/schema/c" 
+       xmlns:context="http://www.springframework.org/schema/context"
+       xmlns:p="http://www.springframework.org/schema/p"
+       xmlns:util="http://www.springframework.org/schema/util"
+       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"
+       default-init-method="initialize"
+       default-destroy-method="destroy">
+    
+    
+    <!-- Aliases used for wiring, especially by other components. In case we want to switch strategies, can do it here -->
+    <alias alias="shibboleth.SOAPClient.SAML" name="SOAPClient.SAML.LocatorMap" />
+    <alias alias="SOAPClient.SAML.HttpClient" name="SOAPClient.HttpClient" />
+    
+
+    <!-- SOAP client and pipeline factory definitions. -->
+         
+    <bean id="SOAPClient.SAML.LocatorMap" class="org.opensaml.soap.client.http.PipelineFactoryHttpSOAPClient">
+        <property name="httpClient" ref="SOAPClient.SAML.HttpClient" />
+        <property name="pipelineFactory" ref="SOAPClient.PipelineFactory.LocatorMap" />
+    </bean>
+    
+    <!-- Pipeline-based SOAP client which selects factory dynamically based on serviceMappings below. -->
+    <bean id="SOAPClient.PipelineFactory.LocatorMap" class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
+        <property name="serviceLocatorInterface" value="org.opensaml.messaging.pipeline.httpclient.HttpClientMessagePipelineFactory" />
+        <property name="serviceMappings">
+            <props>
+                <prop key="SAML2.ArtifactDecoder">SOAPClient.SAML2.Pipeline</prop>
+            </props>
+        </property>
+    </bean>
+    
+    
+    <!-- Pipelines. -->
+    
+    <!-- A base abstract pipeline bean for SAML 2.  The encoder and decoder are always going to be the same so factor out to a parent bean.
+         IMPORTANT: actual instances of this bean and the encoder/decoder below MUST be prototypes, as they are per-request instance. -->
+    <bean id="SOAPClient.SAML2.Pipeline.Abstract" abstract="true" class="org.opensaml.messaging.pipeline.httpclient.BasicHttpClientMessagePipeline">
+        <constructor-arg>
+            <bean scope="prototype" init-method="" class="org.opensaml.saml.saml2.binding.encoding.impl.HttpClientRequestSOAP11Encoder" />
+        </constructor-arg>
+        <constructor-arg>
+            <bean scope="prototype" init-method="" class="org.opensaml.saml.saml2.binding.decoding.impl.HttpClientResponseSOAP11Decoder" />
+        </constructor-arg>
+    </bean>
+    
+    
+    <!-- SAML-specific SOAP client beans. -->
+    
+    <!-- Basic SAML 2 pipeline. -->
+    <bean id="SOAPClient.SAML2.Pipeline" scope="prototype" parent="SOAPClient.SAML2.Pipeline.Abstract">
+    
+        <property name="outboundPayloadHandler">
+            <bean scope="prototype" class="org.opensaml.messaging.handler.impl.BasicMessageHandlerChain">
+                <property name="handlers">
+                    <util:list>
+                    
+                        <ref bean="SOAPClient.InitializeRelyingPartyContexFromSAMLPeer" />
+                        
+                        <ref bean="SOAPClient.SelectRelyingPartyConfiguration" />
+                        
+                        <ref bean="SOAPClient.SelectProfileConfiguration" />
+                    
+                        <bean scope="prototype" class="org.opensaml.saml.common.binding.impl.PopulateSignatureSigningParametersHandler" 
+                            p:signatureSigningParametersResolver-ref="shibboleth.SignatureSigningParametersResolver"
+                            p:configurationLookupStrategy-ref="shibboleth.MessageContext.SignatureSigningConfigurationLookup"
+                            />
+                            
+                        <bean scope="prototype" class="org.opensaml.saml.common.binding.security.impl.SAMLOutboundProtocolMessageSigningHandler" />
+                        
+                    </util:list>
+                </property>
+            </bean>
+        </property>
+        
+        <property name="outboundTransportHandler">
+            <bean scope="prototype" class="org.opensaml.messaging.handler.impl.BasicMessageHandlerChain">
+                <property name="handlers">
+                    <util:list>
+                        <bean scope="prototype" class="org.opensaml.security.messaging.impl.PopulateHttpClientSecurityParametersHandler" 
+                            p:httpClientSecurityParametersResolver-ref="shibboleth.HttpClientSecurityParametersResolver"
+                            p:configurationLookupStrategy-ref="shibboleth.MessageContext.HttpClientSecurityConfigurationLookup"
+                            />
+                    </util:list>
+                </property>
+            </bean>
+        </property>
+        
+        <property name="inboundHandler">
+            <bean scope="prototype" class="org.opensaml.messaging.handler.impl.BasicMessageHandlerChain">
+                <property name="handlers">
+                    <util:list>
+                    
+                        <!--  TODO -->
+                        <bean scope="prototype" class="org.opensaml.saml.common.binding.impl.SAMLProtocolAndRoleHandler" >
+                            <property name="protocol">
+                                <util:constant static-field="org.opensaml.saml.common.xml.SAMLConstants.SAML20P_NS" />
+                            </property>
+                            <property name="role">
+                                <util:constant static-field="org.opensaml.saml.saml2.metadata.SPSSODescriptor.DEFAULT_ELEMENT_NAME" />
+                            </property>
+                        </bean>
+                        
+                        <bean scope="prototype" class="org.opensaml.xmlsec.messaging.impl.PopulateSignatureValidationParametersHandler"
+                            p:signatureValidationParametersResolver-ref="shibboleth.SignatureValidationParametersResolver"
+                            p:configurationLookupStrategy-ref="shibboleth.MessageContext.SignatureValidationConfigurationLookup" />
+                        
+                        <bean scope="prototype" class="org.opensaml.saml.common.binding.security.impl.MessageReplaySecurityHandler"
+                            p:replayCache-ref="shibboleth.ReplayCache"
+                            p:expires="%{idp.policy.messageLifetime:PT3M}" />
+                        
+                        <bean scope="prototype" class="org.opensaml.saml.common.binding.security.impl.MessageLifetimeSecurityHandler"
+                            p:messageLifetime="%{idp.policy.messageLifetime:PT3M}"
+                            p:clockSkew="%{idp.policy.clockSkew:PT3M}" />
+                        
+                        <bean scope="prototype" class="org.opensaml.saml.common.binding.security.impl.SAMLProtocolMessageXMLSignatureSecurityHandler" />
+                        
+                        <bean scope="prototype" class="org.opensaml.messaging.handler.impl.CheckMandatoryIssuer">
+                            <property name="issuerLookupStrategy">
+                                <bean class="org.opensaml.saml.common.messaging.context.navigate.SAMLMessageContextIssuerFunction" />
+                            </property>
+                        </bean>
+                        
+                        <bean scope="prototype" class="org.opensaml.messaging.handler.impl.CheckMandatoryAuthentication">
+                            <property name="authenticationLookupStrategy">
+                                <bean class="org.opensaml.saml.common.messaging.context.navigate.SAMLMessageContextAuthenticationFunction" />
+                            </property>
+                        </bean>
+                        
+                    </util:list>
+                </property>
+            </bean>
+        </property>
+    </bean>
+    
+    
+    
+    
+    <!--  Supporting beans. -->
+    <bean id="SOAPClient.SOAPClientSecurityProfileIdLookup" 
+        class="org.opensaml.soap.client.security.SOAPClientSecurityProfileIdLookupFunction" />
+    
+    <bean id="SOAPClient.InitializeRelyingPartyContexFromSAMLPeer"
+        class="net.shibboleth.idp.saml.messaging.impl.InitializeRelyingPartyContextFromSAMLPeer" scope="prototype" />
+        
+    <bean id="SOAPClient.SelectRelyingPartyConfiguration"
+        class="net.shibboleth.idp.profile.messaging.impl.SelectRelyingPartyConfiguration" scope="prototype"
+        p:relyingPartyConfigurationResolver-ref="shibboleth.CriteriaRelyingPartyConfigurationResolver" />
+        
+    <bean id="SOAPClient.SelectProfileConfiguration"
+        class="net.shibboleth.idp.profile.messaging.impl.SelectProfileConfiguration" scope="prototype"
+        p:profiledIdLookupStrategy-ref="SOAPClient.SOAPClientSecurityProfileIdLookup" />
+        
+    <!-- TODO probably not we want in the end, just for initial testing. -->
+    <bean id="SOAPClient.HttpClient" parent="shibboleth.NonCachingHttpClient"
+        p:tLSSocketFactory-ref="shibboleth.SecurityEnhancedTLSSocketFactoryWithClientTLSOnly" />
+    
+    
+
+</beans>
\ No newline at end of file
diff --git a/idp-conf/src/main/resources/system/conf/utilities.xml b/idp-conf/src/main/resources/system/conf/utilities.xml
index 9350dcb..3249898 100644
--- a/idp-conf/src/main/resources/system/conf/utilities.xml
+++ b/idp-conf/src/main/resources/system/conf/utilities.xml
@@ -189,6 +189,16 @@
         p:selfConfiguration="#{getObject('shibboleth.SelfEncryptionConfiguration')}"
         p:includeProfileDefaultConfiguration="%{idp.encryption.self.includeProfileDefaultConfiguration:false}"
         p:relyingPartyConfigurationResolver-ref="shibboleth.RelyingPartyConfigurationResolver" />
+        
+    <bean id="shibboleth.MessageContext.SignatureValidationConfigurationLookup"
+        class="net.shibboleth.idp.profile.config.navigate.messaging.SignatureValidationConfigurationLookupFunction"
+        p:relyingPartyConfigurationResolver-ref="shibboleth.RelyingPartyConfigurationResolver" />
+    <bean id="shibboleth.MessageContext.SignatureSigningConfigurationLookup"
+        class="net.shibboleth.idp.profile.config.navigate.messaging.SignatureSigningConfigurationLookupFunction"
+        p:relyingPartyConfigurationResolver-ref="shibboleth.RelyingPartyConfigurationResolver" />
+    <bean id="shibboleth.MessageContext.HttpClientSecurityConfigurationLookup"
+        class="net.shibboleth.idp.profile.config.navigate.messaging.HttpClientSecurityConfigurationLookupFunction"
+        p:relyingPartyConfigurationResolver-ref="shibboleth.RelyingPartyConfigurationResolver" />
 
     <util:list id="shibboleth.SAML1Status.VersionMismatch">
         <util:constant static-field="org.opensaml.saml.saml1.core.StatusCode.VERSION_MISMATCH" />
diff --git a/idp-conf/src/main/resources/system/flows/saml/saml-abstract-beans.xml b/idp-conf/src/main/resources/system/flows/saml/saml-abstract-beans.xml
index 8117f3d..47d70c6 100644
--- a/idp-conf/src/main/resources/system/flows/saml/saml-abstract-beans.xml
+++ b/idp-conf/src/main/resources/system/flows/saml/saml-abstract-beans.xml
@@ -367,5 +367,12 @@
     <bean id="PopulateUserAgentContext"
         class="net.shibboleth.idp.profile.impl.PopulateUserAgentContext" scope="prototype"
         p:httpServletRequest-ref="shibboleth.HttpServletRequest" />
+        
+        
+    <!-- Non-ProfileRequestContext oriented beans, for example for us in SOAPClient. -->        
+    
+    <bean id="ArtifactSupport.SelfEntityIDResolver" 
+        class="net.shibboleth.idp.relyingparty.impl.CriteriaSelfEntityIDResolver"
+        p:relyingPartyConfigurationResolver-ref="shibboleth.CriteriaRelyingPartyConfigurationResolver" />
 
 </beans>
diff --git a/idp-conf/src/main/resources/system/flows/saml/saml2/sso-artifact-beans.xml b/idp-conf/src/main/resources/system/flows/saml/saml2/sso-artifact-beans.xml
index d32880f..74443d5 100644
--- a/idp-conf/src/main/resources/system/flows/saml/saml2/sso-artifact-beans.xml
+++ b/idp-conf/src/main/resources/system/flows/saml/saml2/sso-artifact-beans.xml
@@ -25,13 +25,14 @@
                 p:parserPool-ref="shibboleth.ParserPool"
                 p:httpServletRequest-ref="shibboleth.HttpServletRequest"
                 p:bindingDescriptor-ref="shibboleth.Binding.SAML2Artifact"
-                
-                p:peerEntityRole="#{T(org.opensaml.saml.saml2.metadata.SPSSODescriptor).DEFAULT_ELEMENT_NAME"
+                p:peerEntityRole="#{T(org.opensaml.saml.saml2.metadata.SPSSODescriptor).DEFAULT_ELEMENT_NAME}"
                 p:roleDescriptorResolver-ref="shibboleth.RoleDescriptorResolver"
                 p:identifierGenerationStrategy-ref="shibboleth.DefaultIdentifierGenerationStrategy"
-                p:selfEntityIDResolver-ref="TODO"
+                p:selfEntityIDResolver-ref="ArtifactSupport.SelfEntityIDResolver"
                 p:artifactEndpointResolver-ref="shibboleth.EndpointResolver"
-                p:SOAPClient-ref="TODO"
+                p:SOAPClient-ref="shibboleth.SOAPClient.SAML"
+                p:SOAPPipelineName="SAML2.ArtifactDecoder"
+                p:SOAPClientSecurityConfigurationProfileId="#{T(net.shibboleth.idp.saml.saml2.profile.config.BrowserSSOProfileConfiguration).PROFILE_ID}"
                 />
         </constructor-arg>
     </bean>
diff --git a/idp-profile-api/src/main/java/net/shibboleth/idp/profile/config/navigate/messaging/HttpClientSecurityConfigurationLookupFunction.java b/idp-profile-api/src/main/java/net/shibboleth/idp/profile/config/navigate/messaging/HttpClientSecurityConfigurationLookupFunction.java
new file mode 100644
index 0000000..62e3904
--- /dev/null
+++ b/idp-profile-api/src/main/java/net/shibboleth/idp/profile/config/navigate/messaging/HttpClientSecurityConfigurationLookupFunction.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.profile.config.navigate.messaging;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.security.httpclient.HttpClientSecurityConfiguration;
+import org.opensaml.security.httpclient.HttpClientSecuritySupport;
+
+import net.shibboleth.idp.profile.config.ProfileConfiguration;
+import net.shibboleth.idp.profile.config.SecurityConfiguration;
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
+import net.shibboleth.idp.profile.context.navigate.messaging.AbstractRelyingPartyLookupFunction;
+import net.shibboleth.idp.relyingparty.RelyingPartyConfigurationResolver;
+
+/**
+ * A {@link MessageContext} function that returns a {@link HttpClientSecurityConfiguration} list 
+ * by way of various lookup strategies.
+ * 
+ * <p>If a specific setting is unavailable, a null value is returned.</p>
+ */
+public class HttpClientSecurityConfigurationLookupFunction
+        extends AbstractRelyingPartyLookupFunction<List<HttpClientSecurityConfiguration>> {
+    
+    /** A resolver for default security configurations. */
+    @Nullable private RelyingPartyConfigurationResolver rpResolver;
+
+    /**
+     * Set the resolver for default security configurations.
+     * 
+     * @param resolver the resolver to use
+     */
+    public void setRelyingPartyConfigurationResolver(@Nullable final RelyingPartyConfigurationResolver resolver) {
+        rpResolver = resolver;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    @Nullable public List<HttpClientSecurityConfiguration> apply(@Nullable final MessageContext input) {
+        
+        final List<HttpClientSecurityConfiguration> configs = new ArrayList<>();
+        
+        final RelyingPartyContext rpc = getRelyingPartyContextLookupStrategy().apply(input);
+        if (rpc != null) {
+            final ProfileConfiguration pc = rpc.getProfileConfig();
+            if (pc != null && pc.getSecurityConfiguration() != null) {
+                configs.add(pc.getSecurityConfiguration().getHttpClientSecurityConfiguration());
+            }
+            
+            // Check for a per-profile default (relying party independent) config.
+            if (pc != null && rpResolver != null) {
+                final SecurityConfiguration defaultConfig =
+                        rpResolver.getDefaultSecurityConfiguration(pc.getId());
+                if (defaultConfig != null && defaultConfig.getHttpClientSecurityConfiguration() != null) {
+                    configs.add(defaultConfig.getHttpClientSecurityConfiguration());
+                }
+            }
+        }
+
+        configs.add(HttpClientSecuritySupport.getGlobalHttpClientSecurityConfiguration());
+        
+        return configs;
+    }
+
+}
\ No newline at end of file
diff --git a/idp-profile-api/src/main/java/net/shibboleth/idp/profile/config/navigate/messaging/SignatureSigningConfigurationLookupFunction.java b/idp-profile-api/src/main/java/net/shibboleth/idp/profile/config/navigate/messaging/SignatureSigningConfigurationLookupFunction.java
new file mode 100644
index 0000000..ac90740
--- /dev/null
+++ b/idp-profile-api/src/main/java/net/shibboleth/idp/profile/config/navigate/messaging/SignatureSigningConfigurationLookupFunction.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.profile.config.navigate.messaging;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.xmlsec.SecurityConfigurationSupport;
+import org.opensaml.xmlsec.SignatureSigningConfiguration;
+
+import net.shibboleth.idp.profile.config.ProfileConfiguration;
+import net.shibboleth.idp.profile.config.SecurityConfiguration;
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
+import net.shibboleth.idp.profile.context.navigate.messaging.AbstractRelyingPartyLookupFunction;
+import net.shibboleth.idp.relyingparty.RelyingPartyConfigurationResolver;
+
+/**
+ * A {@link MessageContext} function that returns a {@link SignatureSigningConfiguration} list 
+ * by way of various lookup strategies.
+ * 
+ * <p>If a specific setting is unavailable, a null value is returned.</p>
+ */
+public class SignatureSigningConfigurationLookupFunction
+        extends AbstractRelyingPartyLookupFunction<List<SignatureSigningConfiguration>> {
+    
+    /** A resolver for default security configurations. */
+    @Nullable private RelyingPartyConfigurationResolver rpResolver;
+
+    /**
+     * Set the resolver for default security configurations.
+     * 
+     * @param resolver the resolver to use
+     */
+    public void setRelyingPartyConfigurationResolver(@Nullable final RelyingPartyConfigurationResolver resolver) {
+        rpResolver = resolver;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    @Nullable public List<SignatureSigningConfiguration> apply(@Nullable final MessageContext input) {
+        
+        final List<SignatureSigningConfiguration> configs = new ArrayList<>();
+        
+        final RelyingPartyContext rpc = getRelyingPartyContextLookupStrategy().apply(input);
+        if (rpc != null) {
+            final ProfileConfiguration pc = rpc.getProfileConfig();
+            if (pc != null && pc.getSecurityConfiguration() != null) {
+                configs.add(pc.getSecurityConfiguration().getSignatureSigningConfiguration());
+            }
+            
+            // Check for a per-profile default (relying party independent) config.
+            if (pc != null && rpResolver != null) {
+                final SecurityConfiguration defaultConfig =
+                        rpResolver.getDefaultSecurityConfiguration(pc.getId());
+                if (defaultConfig != null && defaultConfig.getSignatureSigningConfiguration() != null) {
+                    configs.add(defaultConfig.getSignatureSigningConfiguration());
+                }
+            }
+        }
+
+        configs.add(SecurityConfigurationSupport.getGlobalSignatureSigningConfiguration());
+        
+        return configs;
+    }
+
+}
\ No newline at end of file
diff --git a/idp-profile-api/src/main/java/net/shibboleth/idp/profile/config/navigate/messaging/SignatureValidationConfigurationLookupFunction.java b/idp-profile-api/src/main/java/net/shibboleth/idp/profile/config/navigate/messaging/SignatureValidationConfigurationLookupFunction.java
new file mode 100644
index 0000000..cda6e99
--- /dev/null
+++ b/idp-profile-api/src/main/java/net/shibboleth/idp/profile/config/navigate/messaging/SignatureValidationConfigurationLookupFunction.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.profile.config.navigate.messaging;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.xmlsec.SecurityConfigurationSupport;
+import org.opensaml.xmlsec.SignatureValidationConfiguration;
+
+import net.shibboleth.idp.profile.config.ProfileConfiguration;
+import net.shibboleth.idp.profile.config.SecurityConfiguration;
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
+import net.shibboleth.idp.profile.context.navigate.messaging.AbstractRelyingPartyLookupFunction;
+import net.shibboleth.idp.relyingparty.RelyingPartyConfigurationResolver;
+
+/**
+ * A {@link MessageContext} function that returns a {@link SignatureValidationConfiguration} list 
+ * by way of various lookup strategies.
+ * 
+ * <p>If a specific setting is unavailable, a null value is returned.</p>
+ */
+public class SignatureValidationConfigurationLookupFunction
+        extends AbstractRelyingPartyLookupFunction<List<SignatureValidationConfiguration>> {
+    
+    /** A resolver for default security configurations. */
+    @Nullable private RelyingPartyConfigurationResolver rpResolver;
+
+    /**
+     * Set the resolver for default security configurations.
+     * 
+     * @param resolver the resolver to use
+     */
+    public void setRelyingPartyConfigurationResolver(@Nullable final RelyingPartyConfigurationResolver resolver) {
+        rpResolver = resolver;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    @Nullable public List<SignatureValidationConfiguration> apply(@Nullable final MessageContext input) {
+        
+        final List<SignatureValidationConfiguration> configs = new ArrayList<>();
+        
+        final RelyingPartyContext rpc = getRelyingPartyContextLookupStrategy().apply(input);
+        if (rpc != null) {
+            final ProfileConfiguration pc = rpc.getProfileConfig();
+            if (pc != null && pc.getSecurityConfiguration() != null) {
+                configs.add(pc.getSecurityConfiguration().getSignatureValidationConfiguration());
+            }
+            
+            // Check for a per-profile default (relying party independent) config.
+            if (pc != null && rpResolver != null) {
+                final SecurityConfiguration defaultConfig =
+                        rpResolver.getDefaultSecurityConfiguration(pc.getId());
+                if (defaultConfig != null && defaultConfig.getSignatureValidationConfiguration() != null) {
+                    configs.add(defaultConfig.getSignatureValidationConfiguration());
+                }
+            }
+        }
+
+        configs.add(SecurityConfigurationSupport.getGlobalSignatureValidationConfiguration());
+        
+        return configs;
+    }
+
+}
\ No newline at end of file
diff --git a/idp-profile-api/src/main/java/net/shibboleth/idp/profile/context/navigate/messaging/AbstractRelyingPartyLookupFunction.java b/idp-profile-api/src/main/java/net/shibboleth/idp/profile/context/navigate/messaging/AbstractRelyingPartyLookupFunction.java
new file mode 100644
index 0000000..82c4c19
--- /dev/null
+++ b/idp-profile-api/src/main/java/net/shibboleth/idp/profile/context/navigate/messaging/AbstractRelyingPartyLookupFunction.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.profile.context.navigate.messaging;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.messaging.context.InOutOperationContext;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.messaging.context.navigate.ContextDataLookupFunction;
+import org.opensaml.messaging.context.navigate.RecursiveTypedParentContextLookup;
+
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+/**
+ * Abstract base class for a function that requires a {@link RelyingPartyContext}
+ * obtained via a lookup function, by default a child of the {@link InOutOperationContext} 
+ * the parent of the specified {@link MessageContext}.
+ * 
+ * @param <ResultType> return type of function
+ */
+public abstract class AbstractRelyingPartyLookupFunction<ResultType>
+        implements ContextDataLookupFunction<MessageContext,ResultType> {
+
+    /**
+     * Strategy used to locate the {@link RelyingPartyContext} associated with a given {@link MessageContext}.
+     */
+    @Nonnull private Function<MessageContext,RelyingPartyContext> relyingPartyContextLookupStrategy;
+    
+    /** Constructor. */
+    public AbstractRelyingPartyLookupFunction() {
+        relyingPartyContextLookupStrategy = Functions.compose(
+                new ChildContextLookup<InOutOperationContext, RelyingPartyContext>(RelyingPartyContext.class),
+                new RecursiveTypedParentContextLookup<MessageContext,InOutOperationContext>(InOutOperationContext.class)
+                );
+    }
+
+    /**
+     * Set the strategy used to locate the {@link RelyingPartyContext} associated with a given
+     * {@link MessageContext}.
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setRelyingPartyContextLookupStrategy(
+            @Nonnull final Function<MessageContext,RelyingPartyContext> strategy) {
+        relyingPartyContextLookupStrategy =
+                Constraint.isNotNull(strategy, "RelyingPartyContext lookup strategy cannot be null");
+    }
+    
+    /**
+     * Get the strategy used to locate the {@link RelyingPartyContext} associated with a given
+     * {@link MessageContext}.
+     * 
+     * @return lookup strategy
+     */
+    @Nonnull public Function<MessageContext,RelyingPartyContext> getRelyingPartyContextLookupStrategy() {
+        return relyingPartyContextLookupStrategy;
+    }
+
+}
\ No newline at end of file
diff --git a/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/messaging/impl/SelectProfileConfiguration.java b/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/messaging/impl/SelectProfileConfiguration.java
new file mode 100644
index 0000000..3c1f874
--- /dev/null
+++ b/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/messaging/impl/SelectProfileConfiguration.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.profile.messaging.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.InOutOperationContext;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.messaging.context.navigate.RecursiveTypedParentContextLookup;
+import org.opensaml.messaging.handler.AbstractMessageHandler;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+
+import net.shibboleth.idp.profile.config.ProfileConfiguration;
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
+import net.shibboleth.idp.relyingparty.RelyingPartyConfiguration;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+/**
+ * Action that selects the {@link ProfileConfiguration} for the given message context and sets it in the looked-up
+ * {@link RelyingPartyContext}.
+ * 
+ * 
+ * @post InOutOperationContext.getSubcontext(RelyingPartyContext.class).getProfileConfiguration() != null
+ */
+public class SelectProfileConfiguration extends AbstractMessageHandler {
+
+    /** Class logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(SelectProfileConfiguration.class);
+
+    /**
+     * Strategy used to locate the {@link RelyingPartyContext} associated with a given {@link MessageContext}.
+     */
+    @NonnullAfterInit private Function<MessageContext,RelyingPartyContext> relyingPartyContextLookupStrategy;
+    
+    /**
+     * Strategy used to locate the effective profile ID associated with a given {@link MessageContext}.
+     */
+    @Nonnull private Function<MessageContext,String> profileIdLookupStrategy;
+
+    /** The RelyingPartyContext to operate on. */
+    @Nullable private RelyingPartyContext rpCtx;
+    
+    /** Constructor. */
+    public SelectProfileConfiguration() {
+        relyingPartyContextLookupStrategy =   Functions.compose(
+                new ChildContextLookup<InOutOperationContext, RelyingPartyContext>(RelyingPartyContext.class),
+                new RecursiveTypedParentContextLookup<MessageContext,InOutOperationContext>(InOutOperationContext.class)
+                );
+    }
+
+    /**
+     * Set the strategy used to locate the {@link RelyingPartyContext} associated with a given
+     * {@link MessageContext}.
+     * 
+     * @param strategy strategy used to locate the {@link RelyingPartyContext} associated with a given
+     *         {@link MessageContext}
+     */
+    public void setRelyingPartyContextLookupStrategy(
+            @Nonnull final Function<MessageContext,RelyingPartyContext> strategy) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        
+        relyingPartyContextLookupStrategy = Constraint.isNotNull(strategy,
+                "RelyingPartyContext lookup strategy cannot be null");
+    }
+
+    /**
+     * Set the strategy used to locate the effective profile ID associated with a given
+     * {@link MessageContext}.
+     * 
+     * @param strategy strategy used to locate the {@link RelyingPartyContext} associated with a given
+     *         {@link MessageContext}
+     */
+    public void setProfiledIdLookupStrategy(@Nonnull final Function<MessageContext,String> strategy) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        
+        profileIdLookupStrategy = strategy;
+    }
+
+    /** {@inheritDoc} */
+    protected void doInitialize() throws ComponentInitializationException {
+        super.doInitialize();
+        
+        if (profileIdLookupStrategy == null) {
+            throw new ComponentInitializationException("Profile ID lookup strategy was null");
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected boolean doPreInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+        
+        if (!super.doPreInvoke(messageContext)) {
+            return false;
+        }
+        
+        rpCtx = relyingPartyContextLookupStrategy.apply(messageContext);
+        if (rpCtx == null) {
+            log.debug("{} No relying party context associated with this profile request", getLogPrefix());
+            throw new MessageHandlerException("No relying party context associated with this message context");
+        }
+
+        if (rpCtx.getConfiguration() == null) {
+            log.debug("{} No relying party configuration associated with this profile request", getLogPrefix());
+            throw new MessageHandlerException("No relying party configuration associated with this message context");
+        }
+        
+        return true;
+    }
+    
+    /** {@inheritDoc} */
+    @Override
+    protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+
+        final RelyingPartyConfiguration rpConfig = rpCtx.getConfiguration();
+
+        final String profileId = profileIdLookupStrategy.apply(messageContext);
+        if (profileId == null) {
+            log.warn("{} Profile ID is not available from message context for RP configuration (RPID {})",
+                    new Object[] {getLogPrefix(), rpConfig.getId(), rpCtx.getRelyingPartyId(),});
+            throw new MessageHandlerException("Profile ID is not available from message context");
+        }
+        
+        final ProfileConfiguration profileConfiguration = rpConfig.getProfileConfiguration(profileId);
+        if (profileConfiguration == null) {
+            log.warn("{} Profile {} is not available for RP configuration {} (RPID {})",
+                    new Object[] {getLogPrefix(), profileId, rpConfig.getId(), rpCtx.getRelyingPartyId(),});
+            throw new MessageHandlerException("Profile is not available for RP configuration");
+        } else {
+            rpCtx.setProfileConfig(profileConfiguration);
+        }
+    }
+    
+}
\ No newline at end of file
diff --git a/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/messaging/impl/SelectRelyingPartyConfiguration.java b/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/messaging/impl/SelectRelyingPartyConfiguration.java
new file mode 100644
index 0000000..659312e
--- /dev/null
+++ b/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/messaging/impl/SelectRelyingPartyConfiguration.java
@@ -0,0 +1,149 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.profile.messaging.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.core.criterion.EntityIdCriterion;
+import org.opensaml.messaging.context.InOutOperationContext;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.messaging.context.navigate.RecursiveTypedParentContextLookup;
+import org.opensaml.messaging.handler.AbstractMessageHandler;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
+import net.shibboleth.idp.relyingparty.CriteriaRelyingPartyConfigurationResolver;
+import net.shibboleth.idp.relyingparty.RelyingPartyConfiguration;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+
+/**
+ * This message handler attempts to resolve a {@link RelyingPartyConfiguration} and adds it to the {@link RelyingPartyContext}
+ * that was looked up.
+ * 
+ * @post If a {@link RelyingPartyContext} is located, it will be populated with a non-null result of applying
+ * the supplied {@link CriteriaRelyingPartyConfigurationResolver} to the {@link RelyingPartyContext#getRelyingPartyId()}.
+ */
+public final class SelectRelyingPartyConfiguration extends AbstractMessageHandler {
+
+    /** Class logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(SelectRelyingPartyConfiguration.class);
+
+    /** Resolver used to look up relying party configurations. */
+    @NonnullAfterInit private CriteriaRelyingPartyConfigurationResolver rpConfigResolver;
+
+    /**
+     * Strategy used to locate the {@link RelyingPartyContext} associated with a given {@link MessageContext}.
+     */
+    @Nonnull private Function<MessageContext, RelyingPartyContext> relyingPartyContextLookupStrategy;
+
+    /** The {@link RelyingPartyContext} to manipulate. */
+    @Nullable private RelyingPartyContext relyingPartyCtx;
+    
+    /** Constructor. */
+    public SelectRelyingPartyConfiguration() {
+        relyingPartyContextLookupStrategy = Functions.compose(
+                new ChildContextLookup<InOutOperationContext, RelyingPartyContext>(RelyingPartyContext.class),
+                new RecursiveTypedParentContextLookup<MessageContext,InOutOperationContext>(InOutOperationContext.class)
+                );
+    }
+
+    /**
+     * Set the relying party config resolver to use.
+     * 
+     * @param resolver  the resolver to use
+     */
+    public void setRelyingPartyConfigurationResolver(@Nonnull final CriteriaRelyingPartyConfigurationResolver resolver) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        
+        rpConfigResolver = Constraint.isNotNull(resolver, "Relying party configuration resolver cannot be null");
+    }
+    
+    /**
+     * Set the strategy used to locate the {@link RelyingPartyContext} associated with a given
+     * {@link MessageContext}.
+     * 
+     * @param strategy strategy used to locate the {@link RelyingPartyContext} associated with a given
+     *            {@link MessageContext}
+     */
+    public void setRelyingPartyContextLookupStrategy(
+            @Nonnull final Function<MessageContext, RelyingPartyContext> strategy) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+        relyingPartyContextLookupStrategy =
+                Constraint.isNotNull(strategy, "RelyingPartyContext lookup strategy cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void doInitialize() throws ComponentInitializationException {
+        super.doInitialize();
+        
+        if (rpConfigResolver == null) {
+            throw new ComponentInitializationException("RelyingPartyConfigurationResolver cannot be null");
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean doPreInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+        relyingPartyCtx = relyingPartyContextLookupStrategy.apply(messageContext);
+        if (relyingPartyCtx == null) {
+            log.debug("{} No relying party context available", getLogPrefix());
+            throw new MessageHandlerException("No relying party context available");
+        }
+        
+        if (relyingPartyCtx.getRelyingPartyId() == null) {
+            log.debug("{} No relying party ID available", getLogPrefix());
+            throw new MessageHandlerException("No relying party ID available");
+        }
+        
+        return super.doPreInvoke(messageContext);
+    }
+    
+    /** {@inheritDoc} */
+    @Override
+    public void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+
+        try {
+            final CriteriaSet criteria = new CriteriaSet(new EntityIdCriterion(relyingPartyCtx.getRelyingPartyId()));
+            final RelyingPartyConfiguration config = rpConfigResolver.resolveSingle(criteria);
+            if (config == null) {
+                log.debug("{} No relying party configuration applies to this request", getLogPrefix());
+                throw new MessageHandlerException("No relying party configuration resolved for this request");
+            }
+
+            log.debug("{} Found relying party configuration {} for request", getLogPrefix(), config.getId());
+            relyingPartyCtx.setConfiguration(config);
+        } catch (final ResolverException e) {
+            log.error("{} Error trying to resolve relying party configuration", getLogPrefix(), e);
+            throw new MessageHandlerException("Error trying to resolve relying party configuration");
+        }
+    }
+}
\ No newline at end of file
diff --git a/idp-profile-impl/src/main/java/net/shibboleth/idp/relyingparty/impl/CriteriaSelfEntityIDResolver.java b/idp-profile-impl/src/main/java/net/shibboleth/idp/relyingparty/impl/CriteriaSelfEntityIDResolver.java
new file mode 100644
index 0000000..f33444c
--- /dev/null
+++ b/idp-profile-impl/src/main/java/net/shibboleth/idp/relyingparty/impl/CriteriaSelfEntityIDResolver.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.relyingparty.impl;
+
+import java.util.Collections;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.idp.relyingparty.CriteriaRelyingPartyConfigurationResolver;
+import net.shibboleth.idp.relyingparty.RelyingPartyConfiguration;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.component.AbstractIdentifiedInitializableComponent;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.component.IdentifiableComponent;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+import net.shibboleth.utilities.java.support.resolver.Resolver;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+
+/**
+ * Resolver which uses an instance of {@link CriteriaRelyingPartyConfigurationResolver} to
+ * resolve the self entityID.
+ * 
+ * <p>
+ * The required and allowed criteria are the same as the {@link CriteriaRelyingPartyConfigurationResolver}
+ * implementation in use.
+ * </p>
+ */
+public class CriteriaSelfEntityIDResolver extends AbstractIdentifiedInitializableComponent
+    implements Resolver<String, CriteriaSet>, IdentifiableComponent {
+    
+    /** Logger. */
+    private Logger log = LoggerFactory.getLogger(CriteriaSelfEntityIDResolver.class);
+    
+    /** The CriteriaRelyingPartyConfigurationResolver to which to delegate. */
+    @NonnullAfterInit private CriteriaRelyingPartyConfigurationResolver rpcResolver;
+    
+    /** Constructor. */
+    public CriteriaSelfEntityIDResolver() {
+        super();
+    }
+    
+    /**
+     * Set the {@link CriteriaRelyingPartyConfigurationResolver} instance to which to delegate.
+     * 
+     * @param resolver the relying party resolver 
+     */
+    public void setRelyingPartyConfigurationResolver(
+            @Nullable final CriteriaRelyingPartyConfigurationResolver resolver) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        rpcResolver = resolver;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setId(@Nonnull final String componentId) {
+        super.setId(componentId);
+    }
+
+    /** {@inheritDoc} */
+    protected void doInitialize() throws ComponentInitializationException {
+        super.doInitialize();
+        if (rpcResolver == null) {
+            throw new ComponentInitializationException("CriteriaRelyingPartyConfigurationResolver was null");
+        }
+    }
+
+    /** {@inheritDoc} */
+    protected void doDestroy() {
+        rpcResolver = null;
+        super.doDestroy();
+    }
+
+    /** {@inheritDoc} */
+    @Nonnull @NonnullElements public Iterable<String> resolve(
+            @Nullable final CriteriaSet criteria) throws ResolverException {
+        ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
+        ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+        
+        final String entityID = resolveSingle(criteria);
+        if (entityID != null) {
+            return Collections.singletonList(entityID);
+        } else {
+            return Collections.emptyList();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Nullable public String resolveSingle(@Nullable final CriteriaSet criteria) throws ResolverException {
+        ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
+        ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+        
+        final RelyingPartyConfiguration rpc = rpcResolver.resolveSingle(criteria);
+        if (rpc != null) {
+            return rpc.getResponderId();
+        } else {
+            return null;
+            
+        }
+    }
+
+}
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/messaging/impl/InitializeRelyingPartyContextFromSAMLPeer.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/messaging/impl/InitializeRelyingPartyContextFromSAMLPeer.java
new file mode 100644
index 0000000..70219b0
--- /dev/null
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/messaging/impl/InitializeRelyingPartyContextFromSAMLPeer.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.saml.messaging.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.InOutOperationContext;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.messaging.context.navigate.RecursiveTypedParentContextLookup;
+import org.opensaml.messaging.handler.AbstractMessageHandler;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
+import net.shibboleth.idp.saml.profile.impl.SAMLRelyingPartyIdLookupStrategy;
+import net.shibboleth.idp.saml.profile.impl.SAMLVerificationLookupStrategy;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+/**
+ * Message handler that adds a {@link RelyingPartyContext} to the current {@link InOutOperationContext} tree
+ * via a creation function. The context is populated via a lookup strategy to locate a {@link SAMLPeerEntityContext},
+ * by default as a direct child of the parent {@link InOutOperationContext}.
+ * 
+ * @post InOutOperationContext.getSubcontext(RelyingPartyContext.class) != null and populated as above.
+ */
+public class InitializeRelyingPartyContextFromSAMLPeer extends AbstractMessageHandler {
+
+    /** The relying party ID lookup function to inject. */
+    @Nonnull private static final Function<RelyingPartyContext,String> RPID_LOOKUP
+        = new SAMLRelyingPartyIdLookupStrategy();
+
+    /** The verification lookup function to inject. */
+    @Nonnull private static final Function<RelyingPartyContext,Boolean> VERIFY_LOOKUP
+        = new SAMLVerificationLookupStrategy();
+    
+    /** Class logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(InitializeRelyingPartyContextFromSAMLPeer.class);
+
+    /** Strategy that will return or create a {@link RelyingPartyContext}. */
+    @Nonnull private Function<MessageContext,RelyingPartyContext> relyingPartyContextCreationStrategy;
+    
+    /** Strategy used to look up the {@link SAMLPeerEntityContext} to draw from. */
+    @Nonnull private Function<MessageContext,SAMLPeerEntityContext> peerEntityContextLookupStrategy;
+
+    /** SAML peer entity context to populate from. */
+    @Nullable private SAMLPeerEntityContext peerEntityCtx;
+    
+    /** Constructor. */
+    public InitializeRelyingPartyContextFromSAMLPeer() {
+        relyingPartyContextCreationStrategy = Functions.compose(
+                new ChildContextLookup<InOutOperationContext, RelyingPartyContext>(RelyingPartyContext.class, true),
+                new RecursiveTypedParentContextLookup<MessageContext,InOutOperationContext>(InOutOperationContext.class)
+                );
+        peerEntityContextLookupStrategy = Functions.compose(
+                new ChildContextLookup<InOutOperationContext, SAMLPeerEntityContext>(SAMLPeerEntityContext.class),
+                new RecursiveTypedParentContextLookup<MessageContext,InOutOperationContext>(InOutOperationContext.class)
+                );
+    }
+
+    /**
+     * Set the strategy used to return or create the {@link RelyingPartyContext}.
+     * 
+     * @param strategy creation strategy
+     */
+    public void setRelyingPartyContextCreationStrategy(
+            @Nonnull final Function<MessageContext,RelyingPartyContext> strategy) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+        relyingPartyContextCreationStrategy =
+                Constraint.isNotNull(strategy, "RelyingPartyContext creation strategy cannot be null");
+    }
+    
+    /**
+     * Set the strategy used to look up the {@link SAMLPeerEntityContext} to draw from.
+     * 
+     * @param strategy strategy used to look up the {@link SAMLPeerEntityContext}
+     */
+    public void setPeerEntityContextLookupStrategy(
+            @Nonnull final Function<MessageContext,SAMLPeerEntityContext> strategy) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+        peerEntityContextLookupStrategy =
+                Constraint.isNotNull(strategy, "SAMLPeerEntityContext lookup strategy cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected boolean doPreInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+        
+        peerEntityCtx = peerEntityContextLookupStrategy.apply(messageContext);
+        if (peerEntityCtx == null) {
+            log.debug("{} Unable to locate SAMLPeerEntityContext", getLogPrefix());
+            throw new MessageHandlerException("Unable to locate SAMLPeerEntityContext");
+        }
+        
+        return super.doPreInvoke(messageContext);
+    }
+        
+    /** {@inheritDoc} */
+    @Override
+    protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+
+        final RelyingPartyContext rpContext = relyingPartyContextCreationStrategy.apply(messageContext);
+        if (rpContext == null) {
+            log.debug("{} Unable to locate or create RelyingPartyContext", getLogPrefix());
+            throw new MessageHandlerException("Unable to locate or create RelyingPartyContext");
+        }
+        
+        log.debug("{} Attaching RelyingPartyContext based on SAML peer {}", getLogPrefix(),
+                peerEntityCtx.getEntityId());
+        rpContext.setRelyingPartyIdContextTree(peerEntityCtx);
+        rpContext.setRelyingPartyIdLookupStrategy(RPID_LOOKUP);
+        rpContext.setVerificationLookupStrategy(VERIFY_LOOKUP);
+    }
+    
+}
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list