[java-plugin-shibd] branch main updated: Untested discovery initiator flow.

Scott Cantor cantor.2 at osu.edu
Fri Jun 27 20:07:17 UTC 2025


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

scantor pushed a commit to branch main
in repository java-plugin-shibd.

View the commit online:
http://git.shibboleth.net/view/?p=java-plugin-shibd.git;a=commit;h=6f5a59e406bd73599136522cc8e95f230d023499

The following commit(s) were added to refs/heads/main by this push:
     new 6f5a59e  Untested discovery initiator flow.
6f5a59e is described below

commit 6f5a59e406bd73599136522cc8e95f230d023499
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Fri Jun 27 16:07:10 2025 -0400

    Untested discovery initiator flow.
---
 .../idp/flows/sp/initiator/disco/disco-beans.xml   |  25 +++
 .../idp/flows/sp/initiator/disco/disco-flow.xml    |  20 ++
 .../shibboleth/sp/profile/InitiatorConstants.java  |   6 +-
 .../sp/profile/impl/IssueDiscoveryRequest.java     | 238 +++++++++++++++++++++
 .../impl/ValidateSessionInitiatorRequest.java      |  49 ++++-
 .../impl/ValidateSessionInitiatorRequestTest.java  |  75 +++++--
 6 files changed, 381 insertions(+), 32 deletions(-)

diff --git a/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/disco/disco-beans.xml b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/disco/disco-beans.xml
new file mode 100644
index 0000000..9a68c38
--- /dev/null
+++ b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/disco/disco-beans.xml
@@ -0,0 +1,25 @@
+<?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">
+
+    <util:constant id="shiibboleth.sp.ProfileId"
+        static-field="net.shibboleth.saml.saml2.profile.config.BrowserSSOProfileConfiguration.PROFILE_ID" />
+
+    <import resource="classpath:/META-INF/net/shibboleth/idp/flows/sp/saml2-common-beans.xml" />
+
+    <bean id="ValidateSessionInitiatorRequest"
+        class="net.shibboleth.sp.profile.impl.ValidateSessionInitiatorRequest" scope="prototype"
+        p:setRequireDiscoveryURL="true"
+        p:setRequireRelyingPartyId="false" />
+        
+    <bean id="IssueDiscoveryRequest"
+        class="net.shibboleth.sp.profile.impl.IssueDiscoveryRequest" scope="prototype"
+        p:httpServletResponseSupplier-ref="shibboleth.RemotedHttpServletResponseSupplier" />
+
+
+</beans>
diff --git a/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/disco/disco-flow.xml b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/disco/disco-flow.xml
new file mode 100644
index 0000000..e3d0241
--- /dev/null
+++ b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/disco/disco-flow.xml
@@ -0,0 +1,20 @@
+<flow xmlns="http://www.springframework.org/schema/webflow" 
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow.xsd"
+    parent="sp/initiator">
+
+    <action-state id="DiscoverySessionInitiator">
+        <evaluate expression="ValidateSessionInitiatorRequest" />
+        <evaluate expression="IssueDiscoveryRequest" />
+        
+        <evaluate expression="'proceed'" />
+
+        <transition on="proceed" to="proceed" />
+        <!-- Remap any other events into a fall-through to the next flow. -->
+        <transition to="ReselectFlow" />
+    </action-state>
+    
+    <!-- The file really exists in this directory, but it's referenced from extending flow-directories -->
+    <bean-import resource="classpath:/META-INF/net/shibboleth/idp/flows/sp/initiator/disco/disco-beans.xml" />
+
+</flow>
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/profile/InitiatorConstants.java b/sp-server-api/src/main/java/net/shibboleth/sp/profile/InitiatorConstants.java
index a3d4f76..db5b868 100644
--- a/sp-server-api/src/main/java/net/shibboleth/sp/profile/InitiatorConstants.java
+++ b/sp-server-api/src/main/java/net/shibboleth/sp/profile/InitiatorConstants.java
@@ -29,10 +29,10 @@ public final class InitiatorConstants {
     /** Legacy entityID input parameter. */
     @Nonnull @NotEmpty public static final String ENTITY_ID = "entityID";
 
-    /** Handler input parameter. */
-    @Nonnull @NotEmpty public static final String HANDLER = "handler";
+    /** Discovery response/return URL input parameter. */
+    @Nonnull @NotEmpty public static final String DISCOVERY_RETURN_URL = "disco_return_url";
 
-    /** Response URL input structure. */
+    /** Response URL input value or structure. */
     @Nonnull @NotEmpty public static final String RESPONSE_URL = "response_url";
 
     /** Private constructor. */
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/IssueDiscoveryRequest.java b/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/IssueDiscoveryRequest.java
new file mode 100644
index 0000000..629d3c6
--- /dev/null
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/IssueDiscoveryRequest.java
@@ -0,0 +1,238 @@
+/*
+ * Licensed 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.sp.profile.impl;
+
+import java.io.IOException;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.action.ActionSupport;
+import org.opensaml.profile.action.EventIds;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+
+import com.google.common.escape.Escaper;
+import com.google.common.net.UrlEscapers;
+
+import net.shibboleth.profile.relyingparty.RelyingPartyConfiguration;
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.resolver.ResolverException;
+import net.shibboleth.sp.ddf.DDF;
+import net.shibboleth.sp.messaging.RemotedHttpServletRequestResponseContext;
+import net.shibboleth.sp.profile.AbstractApplicationAction;
+import net.shibboleth.sp.profile.InitiatorConstants;
+import net.shibboleth.sp.profile.SPConstants;
+
+/**
+ * Generates a request to a discovery service per the protocol defined originally by us under
+ * the SAML TC at OASIS.
+ * 
+ * <p>While referred to as a "SAML" discovery mechanism, it is not SAML-specific or SAML-aware
+ * in any real sense and is just a generic, insecure, redirect-based mechanism to ask a web site
+ * to return a named parameter to a designated return location.</p>
+ * 
+ * @pre The input message has been validated to ensure a {@link InitiatorConstants#DISCOVERY_RETURN_URL}
+ * parameter is present.
+ * 
+ * @event {@link EventIds#PROCEED_EVENT_ID}
+ * @event {@link EventIds#INVALID_MESSAGE}
+ * @event {@link EventIds#MESSAGE_PROC_ERROR}
+ */
+public class IssueDiscoveryRequest extends AbstractApplicationAction {
+
+    /** Class logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(IssueDiscoveryRequest.class);
+
+    /** Strategy used to obtain the discovery URL. */
+    @NonnullAfterInit private Function<ProfileRequestContext,String> discoveryURLLookupStrategy;
+
+    /** Strategy used to obtain the request issuer value. */
+    @Nonnull private Function<ProfileRequestContext,String> issuerLookupStrategy;
+    
+    /** Condition to evaluate to determine passive use. */
+    @Nonnull private Predicate<ProfileRequestContext> passiveCondition;
+    
+    /** Input message. */
+    @NonnullBeforeExec private DDF input;
+    
+    /** The discovery URL to use. */
+    @NonnullBeforeExec private String discoveryURL;
+    
+    /** Value for "entityID" paremeter in request. */
+    @NonnullBeforeExec private String issuer;
+    
+    /** The agent handler URL to return control to. */
+    @NonnullBeforeExec private String returnURL;
+    
+    /** State token. */
+    @Nullable private String state;
+    
+    /** Constructor. */
+    public IssueDiscoveryRequest() {
+        issuerLookupStrategy = new ApplicationDefaultIssuerStrategy();
+        passiveCondition = new DefaultPassiveCondition();
+    }
+    
+    /**
+     * Set the strategy used to obtain the discovery URL.
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setDiscoveryURLLookupStrategy(@Nonnull final Function<ProfileRequestContext,String> strategy) {
+        checkSetterPreconditions();
+        discoveryURLLookupStrategy = Constraint.isNotNull(strategy, "Discovery URL lookup strategy cannot be null");
+    }
+    
+    /**
+     * Set the strategy used to locate the issuer value to use.
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setIssuerLookupStrategy(@Nonnull final Function<ProfileRequestContext,String> strategy) {
+        checkSetterPreconditions();
+        issuerLookupStrategy = Constraint.isNotNull(strategy, "Issuer lookup strategy cannot be null");
+    }
+    
+    /** {@inheritDoc} */
+    @Override
+    protected void doInitialize() throws ComponentInitializationException {
+        super.doInitialize();
+        
+        if (discoveryURLLookupStrategy == null) {
+            throw new ComponentInitializationException("Discovery URL lookup strategy cannot be null");
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
+        
+        if (!super.doPreExecute(profileRequestContext)) {
+            return false;
+        }
+        
+        discoveryURL = discoveryURLLookupStrategy.apply(profileRequestContext);
+        if (discoveryURL == null) {
+            log.error("{} Unable to obtain discovery URL for request", getLogPrefix());
+            ActionSupport.buildEvent(profileRequestContext, EventIds.MESSAGE_PROC_ERROR);
+            return false;
+        }
+        
+        issuer = issuerLookupStrategy.apply(profileRequestContext);
+        if (issuer == null) {
+            ActionSupport.buildEvent(profileRequestContext, EventIds.MESSAGE_PROC_ERROR);
+            log.error("{} Unable to obtain entityID parameter value for discovery request", getLogPrefix());
+            return false;
+        }
+        
+        input = ensureAgentRequestContext().getInput();
+        if (input == null) {
+            ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MESSAGE);
+            log.error("{} No input message from agent", getLogPrefix());
+            return false;
+        }
+        
+        state = input.getmember(SPConstants.STATE).string();
+        
+        // This is checked earlier in the flow, so can be treated as an outright error here.
+        returnURL = input.getmember(InitiatorConstants.DISCOVERY_RETURN_URL).string();
+        if (returnURL == null) {
+            ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MESSAGE);
+            log.error("{} No '{}' input parameter from agent", getLogPrefix(), InitiatorConstants.DISCOVERY_RETURN_URL);
+            return false;
+        }
+
+        return true;
+    }
+    
+    /** {@inheritDoc} */
+    @Override protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
+        
+        // We have to add the state parameter (usually placed there by our calling flow) to the query
+        // string of the already-URL-encoded return URL. We URL-encode the character sequence
+        // "&state=<value>" and append that to the existing URL. This ensures the agent will get our
+        // state token back from the DS to provide to us afterwards.  
+        
+        final Escaper escaper = UrlEscapers.urlFormParameterEscaper();
+        if (state != null) {
+            returnURL += escaper.escape('&' + SPConstants.STATE + '=' + state);
+             // At this point, discoveryURL is already encoded, and thus does not need to
+             // be run through the encoder, which is done this way to ensure that the character set
+             // of this URL is arbitrary from the hub's perspective, to avoid requiiring an explicit
+             // conversion into String, that would depend on charset, This is the essence of the web's
+             // brokenness, that URLs are not in a defined or even *knowable* character encoding
+             // (as only the *body* is covered by the headers sent with the request).
+        }
+        
+        discoveryURL += (discoveryURL.indexOf('?') > 0 ? '&' : '?') + "return=" + returnURL
+                + "&entityID=" + escaper.escape(issuer);
+        if (passiveCondition.test(profileRequestContext)) {
+            discoveryURL += "&isPassive=1";
+        }
+        
+        // Issue a redirect while the remoted layer is loaded in.
+        try {
+            RemotedHttpServletRequestResponseContext.loadCurrent(null,
+                    ensureAgentRequestContext().getRemotedHttpServletResponse());
+            ensureHttpServletResponse().sendRedirect(discoveryURL);
+        } catch (final IOException e) {
+            ActionSupport.buildEvent(profileRequestContext, EventIds.IO_ERROR);
+            log.error("{} I/O error issuing remoted discovery redirect", getLogPrefix(), e);
+        } finally {
+            RemotedHttpServletRequestResponseContext.clearCurrent();
+        }
+    }
+    
+    /**
+     * Derives issuer value from application layer's default settings.
+     */
+    private class ApplicationDefaultIssuerStrategy implements Function<ProfileRequestContext,String> {
+
+        /** {@inheritDoc} */
+        @Nullable public String apply(@Nullable final ProfileRequestContext input) {
+            
+            try {
+                final RelyingPartyConfiguration rpConfig = ensureApplication().resolveSingle(null);
+                if (rpConfig != null) {
+                    return rpConfig.getIssuer(input);
+                }
+            } catch (final ResolverException e) {
+                log.error("{} Error resolving RelyingPartyConfiguration", getLogPrefix(), e);
+            }
+            
+            return null;
+        }
+    }
+
+    /**
+     * Default predicate aware of the two "known" protocols, would have to override for others.
+     */
+    private class DefaultPassiveCondition implements Predicate<ProfileRequestContext> {
+
+        /** {@inheritDoc} */
+        public boolean test(@Nullable final ProfileRequestContext t) {
+            return input.getmember("isPassive").integer() == 1
+                    && "none".equals(input.getmember("prompt").string());
+        }
+    }
+    
+}
\ No newline at end of file
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/ValidateSessionInitiatorRequest.java b/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/ValidateSessionInitiatorRequest.java
index b8fa767..01745cb 100644
--- a/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/ValidateSessionInitiatorRequest.java
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/ValidateSessionInitiatorRequest.java
@@ -25,6 +25,7 @@ import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
 import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.primitive.StringSupport;
 import net.shibboleth.sp.Application;
 import net.shibboleth.sp.ddf.DDF;
 import net.shibboleth.sp.profile.AbstractApplicationAction;
@@ -35,8 +36,8 @@ import net.shibboleth.shared.logic.Constraint;
 
 /**
  * Initiating action of a typical Session Initiator flow, this validates the input message for
- * correctness, and then creates a {@link RelyingPartyContext} based on the identity of the
- * eventual authenticating authority (the IdP/OP/etc.).
+ * correctness, and may create a {@link RelyingPartyContext} based on the identity of the
+ * eventual authenticating authority (the IdP/OP/etc.) if this is part of the request.
  *
  * <p>The authority ID is potentially supplied by the agent in the request, or may be defaulted
  * based on the {@link Application}.</p>
@@ -63,13 +64,15 @@ public class ValidateSessionInitiatorRequest extends AbstractApplicationAction {
     /** Whether to require a relying party ID to exist. */
     private boolean requireRelyingPartyId;
     
+    /** Whether to require a discovery URL input parameter. */
+    private boolean requireDiscoveryURL;
+    
     /** The relying party name to base the inbound context on. */
     @Nullable private String relyingPartyId;
 
     /** Constructor. */
     public ValidateSessionInitiatorRequest() {
         relyingPartyContextCreationStrategy = new ChildContextLookup<>(RelyingPartyContext.class, true);
-        requireRelyingPartyId = true;
     }
     
     /**
@@ -99,6 +102,17 @@ public class ValidateSessionInitiatorRequest extends AbstractApplicationAction {
         requireRelyingPartyId = flag;
     }
     
+    /**
+     * Sets whether to require {@link InitiatorConstants#DISCOVERY_RETURN_URL} input parameter.
+     *
+     * @param flag flag to set
+     */
+    public void setRequireDiscoveryURL(final boolean flag) {
+        checkSetterPreconditions();
+        
+        requireDiscoveryURL = flag;
+    }
+    
     /** {@inheritDoc} */
     @Override
     protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
@@ -114,6 +128,14 @@ public class ValidateSessionInitiatorRequest extends AbstractApplicationAction {
             return false;
         }
 
+        if (requireDiscoveryURL) {
+            if (StringSupport.trimOrNull(input.getmember(InitiatorConstants.DISCOVERY_RETURN_URL).string()) == null) {
+                ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MESSAGE);
+                log.info("{} Input message did not include '{}' parameter", getLogPrefix(), InitiatorConstants.DISCOVERY_RETURN_URL);
+                return false;
+            }
+        }
+        
         relyingPartyId = input.getmember(InitiatorConstants.AUTHORITY).string();
         if (relyingPartyId == null) {
             relyingPartyId = input.getmember(InitiatorConstants.ENTITY_ID).string();
@@ -123,14 +145,25 @@ public class ValidateSessionInitiatorRequest extends AbstractApplicationAction {
                     getLogPrefix());
             relyingPartyId = ensureApplication().getAuthenticatingAuthority(profileRequestContext);
         }
-                
-        if (relyingPartyId == null && requireRelyingPartyId) {
+        
+        if (requireRelyingPartyId) {
+            // Need it, don't have it, signal an error to drop into discovery (if configured).
+            if (relyingPartyId == null) {
+                ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MESSAGE);
+                log.debug("{} Authenticating authority unknown", getLogPrefix());
+                return false;
+            }
+            // Need it, got it, good.
+            return true;
+        } else if (relyingPartyId != null) {
+            // We don't need it, but it's there? We shouldn't be running, because a loop could result.
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MESSAGE);
-            log.error("{} Authenticating authority unknown", getLogPrefix());
+            log.warn("{} Authenticating authority provided, but not expected", getLogPrefix());
+            return false;
+        } else {
+            // Don't need it, don't have it, skip execution phase.
             return false;
         }
-        
-        return true;
     }
     
     /** {@inheritDoc} */
diff --git a/sp-server-impl/src/test/java/net/shibboleth/sp/profile/impl/ValidateSessionInitiatorRequestTest.java b/sp-server-impl/src/test/java/net/shibboleth/sp/profile/impl/ValidateSessionInitiatorRequestTest.java
index a545c97..5e3073f 100644
--- a/sp-server-impl/src/test/java/net/shibboleth/sp/profile/impl/ValidateSessionInitiatorRequestTest.java
+++ b/sp-server-impl/src/test/java/net/shibboleth/sp/profile/impl/ValidateSessionInitiatorRequestTest.java
@@ -23,6 +23,9 @@ import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import com.google.common.escape.Escaper;
+import com.google.common.net.UrlEscapers;
+
 import net.shibboleth.idp.profile.testing.ActionTestingSupport;
 import net.shibboleth.profile.context.RelyingPartyContext;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
@@ -40,7 +43,7 @@ public class ValidateSessionInitiatorRequestTest extends BaseAgplicationActionTe
     @Nonnull @NotEmpty private final static String TEST_VALUE = "https://idp.example.org";
 
     private ValidateSessionInitiatorRequest action;
-        
+
     /**
      * Set up test.
      * 
@@ -49,11 +52,7 @@ public class ValidateSessionInitiatorRequestTest extends BaseAgplicationActionTe
     @BeforeMethod
     public void setUp() throws ComponentInitializationException {
         super.beforeMethod();
-        
         prc.removeSubcontext(RelyingPartyContext.class);
-        
-        action = new ValidateSessionInitiatorRequest();
-        action.initialize();
     }
     
     /**
@@ -62,17 +61,22 @@ public class ValidateSessionInitiatorRequestTest extends BaseAgplicationActionTe
     @AfterMethod
     public void tearDown() {
         action.destroy();
+        action = null;
     }
     
     @Test
-    public void testNoInput() {
+    public void testNoInput() throws ComponentInitializationException {
+        createAction(false, false);
+        
         final Event event = action.execute(src);
         ActionTestingSupport.assertEvent(event, EventIds.INVALID_MESSAGE);
         Assert.assertNull(prc.getSubcontext(RelyingPartyContext.class));
     }
 
     @Test
-    public void testNoResponseURL() {
+    public void testNoHandlerWhenRequired() throws ComponentInitializationException {
+        createAction(false, true);
+        
         final DDF input = new DDF(null).structure();
         arc.setInput(input);
 
@@ -82,9 +86,25 @@ public class ValidateSessionInitiatorRequestTest extends BaseAgplicationActionTe
     }
 
     @Test
-    public void testNoAuthorityWhenRequired() {
+    public void testHandlerWhenRequired() throws ComponentInitializationException {
+        createAction(false, true);
+        
+        final Escaper escaper = UrlEscapers.urlFormParameterEscaper();
+        
+        final DDF input = new DDF(null).structure();
+        input.addmember(InitiatorConstants.DISCOVERY_RETURN_URL).string(escaper.escape("https://sp.example.org/handler?DS=1"));
+        arc.setInput(input);
+
+        final Event event = action.execute(src);
+        ActionTestingSupport.assertProceedEvent(event);
+        Assert.assertNull(prc.getSubcontext(RelyingPartyContext.class));
+    }
+    
+    @Test
+    public void testNoAuthorityWhenRequired() throws ComponentInitializationException {
+        createAction(true, false);
+        
         final DDF input = new DDF(null).structure();
-        input.addmember(InitiatorConstants.RESPONSE_URL).string("foo");
         arc.setInput(input);
 
         final Event event = action.execute(src);
@@ -94,28 +114,24 @@ public class ValidateSessionInitiatorRequestTest extends BaseAgplicationActionTe
 
     @Test
     public void testNoAuthorityWhenNotRequired() throws ComponentInitializationException {
-        action = new ValidateSessionInitiatorRequest();
-        action.setRequireRelyingPartyId(false);
-        action.initialize();
-
+        createAction(false, false);
+        
         final DDF input = new DDF(null).structure();
-        input.addmember(InitiatorConstants.RESPONSE_URL).string("foo");
         arc.setInput(input);
 
         final Event event = action.execute(src);
         ActionTestingSupport.assertProceedEvent(event);
         
-        final RelyingPartyContext rpc = prc.getSubcontext(RelyingPartyContext.class);
-        assert rpc != null;
-        Assert.assertNull(rpc.getRelyingPartyId());
+        Assert.assertNull(prc.getSubcontext(RelyingPartyContext.class));
     }
 
     @Test
-    public void testFallbackAuthority() {
+    public void testFallbackAuthority() throws ComponentInitializationException {
+        createAction(true, false);
+        
         application.setAuthenticatingAuthority(TEST_VALUE);
 
         final DDF input = new DDF(null).structure();
-        input.addmember(InitiatorConstants.RESPONSE_URL).string("foo");
         arc.setInput(input);
 
         final Event event = action.execute(src);
@@ -127,10 +143,11 @@ public class ValidateSessionInitiatorRequestTest extends BaseAgplicationActionTe
     }
 
     @Test
-    public void testInputAuthority() {
+    public void testInputAuthority() throws ComponentInitializationException {
+        createAction(true, false);
+        
         application.setAuthenticatingAuthority(TEST_VALUE);
         final DDF input = new DDF(null).structure();
-        input.addmember(InitiatorConstants.RESPONSE_URL).string("foo");
         input.addmember(InitiatorConstants.AUTHORITY).string(TEST_VALUE + "/shibboleth");
         arc.setInput(input);
         
@@ -142,4 +159,20 @@ public class ValidateSessionInitiatorRequestTest extends BaseAgplicationActionTe
         Assert.assertEquals(rpc.getRelyingPartyId(), TEST_VALUE + "/shibboleth");
     }
 
+    /**
+     * Create action with the specified behavior. 
+     *
+     * @param requireAuthority
+     * @param requireDisco
+     * 
+     * @throws ComponentInitializationException
+     */
+    private void createAction(final boolean requireAuthority, final boolean requireDisco)
+            throws ComponentInitializationException {
+        action = new ValidateSessionInitiatorRequest();
+        action.setRequireRelyingPartyId(requireAuthority);
+        action.setRequireDiscoveryURL(requireDisco);
+        action.initialize();
+    }
+        
 }
\ 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