[java-identity-provider] branch master updated: IDP-1494 - Login flow for proxied SAML authentication

Scott Cantor cantor.2 at osu.edu
Tue Dec 3 09:13:15 EST 2019


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

scantor 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=98d8662e0d78c06f1fbd23cc06bc44b4e268d45c

The following commit(s) were added to refs/heads/master by this push:
       new  98d8662   IDP-1494 - Login flow for proxied SAML authentication
98d8662 is described below

commit 98d8662e0d78c06f1fbd23cc06bc44b4e268d45c
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Dec 3 09:13:08 2019 -0500

    IDP-1494 - Login flow for proxied SAML authentication
    
    https://issues.shibboleth.net/jira/browse/IDP-1494
    
    Revert error handling around discovery.
    Move all conditional discovery logic into parent flow.
    Install discovery hook into obvious login flows.
---
 .../idp/authn/proxy/impl/ExtractDiscoveryResponse.java       | 10 +++++++---
 .../idp/authn/proxy/impl/ExtractDiscoveryResponseTest.java   |  6 ++++--
 .../resources/system/flows/authn/authn-abstract-flow.xml     |  4 ++--
 .../resources/system/flows/authn/external-authn-flow.xml     | 12 +++++++++++-
 .../resources/system/flows/authn/function-authn-flow.xml     | 12 +++++++++++-
 .../src/main/resources/system/flows/authn/mfa-authn-flow.xml | 12 +++++++++++-
 .../resources/system/flows/authn/remoteuser-authn-flow.xml   | 12 +++++++++++-
 .../main/resources/system/flows/authn/saml-authn-flow.xml    | 12 ++++++------
 8 files changed, 63 insertions(+), 17 deletions(-)

diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/proxy/impl/ExtractDiscoveryResponse.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/proxy/impl/ExtractDiscoveryResponse.java
index 6b57360..2dad4ed 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/proxy/impl/ExtractDiscoveryResponse.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/proxy/impl/ExtractDiscoveryResponse.java
@@ -21,9 +21,11 @@ import javax.annotation.Nonnull;
 import javax.servlet.http.HttpServletRequest;
 
 import net.shibboleth.idp.authn.AbstractAuthenticationAction;
+import net.shibboleth.idp.authn.AuthnEventIds;
 import net.shibboleth.idp.authn.context.AuthenticationContext;
 import net.shibboleth.utilities.java.support.primitive.StringSupport;
 
+import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -32,9 +34,10 @@ import org.slf4j.LoggerFactory;
  * An action that extracts a discovery service result and copies it to the {@link AuthenticationContext}.
  * 
  * @event {@link org.opensaml.profile.action.EventIds#PROCEED_EVENT_ID}
+ * @event {@link AuthnEventIds#NO_CREDENTIALS}
  * @pre <pre>ProfileRequestContext.getSubcontext(AuthenticationContext.class) != null</pre>
  * @post If getHttpServletRequest() != null, the content of the "entityID" parameter will be
- * added via {@link AuthenticationContext#setAuthenticatingAuthority(String)}.
+ * set via {@link AuthenticationContext#setAuthenticatingAuthority(String)}.
  */
 public class ExtractDiscoveryResponse extends AbstractAuthenticationAction {
 
@@ -49,14 +52,15 @@ public class ExtractDiscoveryResponse extends AbstractAuthenticationAction {
         final HttpServletRequest request = getHttpServletRequest();
         if (request == null) {
             log.error("{} Profile action does not contain an HttpServletRequest", getLogPrefix());
+            ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.NO_CREDENTIALS);
             return;
         }
 
         final String entityID = StringSupport.trimOrNull(request.getParameter("entityID"));
         
         if (entityID == null) {
-            log.debug("{} No entityID parameter found", getLogPrefix());
-            return;
+            log.info("{} No entityID parameter returned from DS, IdP discovery failed", getLogPrefix());
+            ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.NO_CREDENTIALS);
         }
 
         authenticationContext.setAuthenticatingAuthority(entityID);
diff --git a/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/proxy/impl/ExtractDiscoveryResponseTest.java b/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/proxy/impl/ExtractDiscoveryResponseTest.java
index 3e05b67..f003ad4 100644
--- a/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/proxy/impl/ExtractDiscoveryResponseTest.java
+++ b/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/proxy/impl/ExtractDiscoveryResponseTest.java
@@ -17,6 +17,8 @@
 
 package net.shibboleth.idp.authn.proxy.impl;
 
+
+import net.shibboleth.idp.authn.AuthnEventIds;
 import net.shibboleth.idp.authn.context.AuthenticationContext;
 import net.shibboleth.idp.authn.impl.BaseAuthenticationContextTest;
 import net.shibboleth.idp.profile.ActionTestingSupport;
@@ -45,14 +47,14 @@ public class ExtractDiscoveryResponseTest extends BaseAuthenticationContextTest
         action.initialize();
         final Event event = action.execute(src);
         
-        ActionTestingSupport.assertProceedEvent(event);
+        ActionTestingSupport.assertEvent(event, AuthnEventIds.NO_CREDENTIALS);
         Assert.assertNull(prc.getSubcontext(AuthenticationContext.class).getAuthenticatingAuthority());
     }
 
     @Test public void testFailure() throws Exception {
         final Event event = action.execute(src);
         
-        ActionTestingSupport.assertProceedEvent(event);
+        ActionTestingSupport.assertEvent(event, AuthnEventIds.NO_CREDENTIALS);
         Assert.assertNull(prc.getSubcontext(AuthenticationContext.class).getAuthenticatingAuthority());
     }
 
diff --git a/idp-conf/src/main/resources/system/flows/authn/authn-abstract-flow.xml b/idp-conf/src/main/resources/system/flows/authn/authn-abstract-flow.xml
index 5491c5b..c9bce65 100644
--- a/idp-conf/src/main/resources/system/flows/authn/authn-abstract-flow.xml
+++ b/idp-conf/src/main/resources/system/flows/authn/authn-abstract-flow.xml
@@ -39,9 +39,9 @@
     <end-state id="SubjectCanonicalizationError" />
     <end-state id="InvalidCSRFToken" />
 
-    <!-- Support for discovery implemented via branch to DoDiscovery action. -->
+    <!-- Support for discovery implemented via child flow branch to DoDiscovery action. -->
     <decision-state id="DoDiscovery">
-        <if test="opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext)).getAuthenticatingAuthority() == null"
+        <if test="opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext)).getAttemptedFlow().isDiscoveryRequired() and opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext)).getAuthenticatingAuthority() == null"
             then="CallDiscovery"
             else="PostDiscovery" />
     </decision-state>
diff --git a/idp-conf/src/main/resources/system/flows/authn/external-authn-flow.xml b/idp-conf/src/main/resources/system/flows/authn/external-authn-flow.xml
index 4e6461b..af53c01 100644
--- a/idp-conf/src/main/resources/system/flows/authn/external-authn-flow.xml
+++ b/idp-conf/src/main/resources/system/flows/authn/external-authn-flow.xml
@@ -5,7 +5,17 @@
 
     <!-- This is a login flow for external authentication handled outside the webflow engine. -->
     
-    <view-state id="ExternalTransfer" view="externalRedirect:#{T(net.shibboleth.idp.authn.ExternalAuthentication).getExternalRedirect(flowRequestContext.getActiveFlow().getApplicationContext().getBean('shibboleth.authn.External.externalAuthnPathStrategy').apply(opensamlProfileRequestContext), flowExecutionContext.getKey().toString())}">
+    <on-start>
+        <!-- If installed, this can bypass discovery. -->
+        <evaluate expression="flowRequestContext.getActiveFlow().getApplicationContext().containsBean('shibboleth.authn.External.discoveryFunction') ? opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext)).setAuthenticatingAuthority(flowRequestContext.getActiveFlow().getApplicationContext().getBean('shibboleth.authn.External.discoveryFunction').apply(opensamlProfileRequestContext)) : null" />
+    </on-start>
+
+    <action-state id="Start">
+        <evaluate expression="'proceed'" />
+        <transition on="proceed" to="DoDiscovery" />
+    </action-state>
+    
+    <view-state id="PostDiscovery" view="externalRedirect:#{T(net.shibboleth.idp.authn.ExternalAuthentication).getExternalRedirect(flowRequestContext.getActiveFlow().getApplicationContext().getBean('shibboleth.authn.External.externalAuthnPathStrategy').apply(opensamlProfileRequestContext), flowExecutionContext.getKey().toString())}">
         <attribute name="csrf_excluded" value="true" type="boolean"/>
         <on-render>
             <evaluate expression="opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext)).addSubcontext(new net.shibboleth.idp.authn.context.ExternalAuthenticationContext(new net.shibboleth.idp.authn.impl.ExternalAuthenticationImpl(calledAsExtendedFlow?:false)), true).setFlowExecutionUrl(flowExecutionUrl + '&_eventId_proceed=1')" />
diff --git a/idp-conf/src/main/resources/system/flows/authn/function-authn-flow.xml b/idp-conf/src/main/resources/system/flows/authn/function-authn-flow.xml
index e6c4072..4a962ed 100644
--- a/idp-conf/src/main/resources/system/flows/authn/function-authn-flow.xml
+++ b/idp-conf/src/main/resources/system/flows/authn/function-authn-flow.xml
@@ -5,7 +5,17 @@
 
     <!-- This is a login flow for function-driven authentication. -->
     
-    <action-state id="CallFunction">
+    <on-start>
+        <!-- If installed, this can bypass discovery. -->
+        <evaluate expression="flowRequestContext.getActiveFlow().getApplicationContext().containsBean('shibboleth.authn.Function.discoveryFunction') ? opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext)).setAuthenticatingAuthority(flowRequestContext.getActiveFlow().getApplicationContext().getBean('shibboleth.authn.Function.discoveryFunction').apply(opensamlProfileRequestContext)) : null" />
+    </on-start>
+
+    <action-state id="Start">
+        <evaluate expression="'proceed'" />
+        <transition on="proceed" to="DoDiscovery" />
+    </action-state>
+    
+    <action-state id="PostDiscovery">
         <evaluate expression="ValidateFunctionResult" />
         <evaluate expression="PopulateSubjectCanonicalizationContext" />
         <evaluate expression="'proceed'" />
diff --git a/idp-conf/src/main/resources/system/flows/authn/mfa-authn-flow.xml b/idp-conf/src/main/resources/system/flows/authn/mfa-authn-flow.xml
index 020d428..895a22d 100644
--- a/idp-conf/src/main/resources/system/flows/authn/mfa-authn-flow.xml
+++ b/idp-conf/src/main/resources/system/flows/authn/mfa-authn-flow.xml
@@ -4,7 +4,17 @@
     
     <!-- This is a login flow for executing an arbitrary multi-factor workflow consisting of other flows. -->
     
-    <action-state id="PopulateMultiFactorAuthenticationContext">
+    <on-start>
+        <!-- If installed, this can bypass discovery. -->
+        <evaluate expression="flowRequestContext.getActiveFlow().getApplicationContext().containsBean('shibboleth.authn.MFA.discoveryFunction') ? opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext)).setAuthenticatingAuthority(flowRequestContext.getActiveFlow().getApplicationContext().getBean('shibboleth.authn.MFA.discoveryFunction').apply(opensamlProfileRequestContext)) : null" />
+    </on-start>
+
+    <action-state id="Start">
+        <evaluate expression="'proceed'" />
+        <transition on="proceed" to="DoDiscovery" />
+    </action-state>
+    
+    <action-state id="PostDiscovery">
         <evaluate expression="PopulateMultiFactorAuthenticationContext" />
         <evaluate expression="'proceed'" />
         
diff --git a/idp-conf/src/main/resources/system/flows/authn/remoteuser-authn-flow.xml b/idp-conf/src/main/resources/system/flows/authn/remoteuser-authn-flow.xml
index c061b64..6a35d00 100644
--- a/idp-conf/src/main/resources/system/flows/authn/remoteuser-authn-flow.xml
+++ b/idp-conf/src/main/resources/system/flows/authn/remoteuser-authn-flow.xml
@@ -4,8 +4,18 @@
       parent="authn.abstract">
 
     <!-- This is a login flow for container-based pseudo-authentication implemented via external authentication. -->
+
+    <on-start>
+        <!-- If installed, this can bypass discovery. -->
+        <evaluate expression="flowRequestContext.getActiveFlow().getApplicationContext().containsBean('shibboleth.authn.RemoteUser.discoveryFunction') ? opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext)).setAuthenticatingAuthority(flowRequestContext.getActiveFlow().getApplicationContext().getBean('shibboleth.authn.RemoteUser.discoveryFunction').apply(opensamlProfileRequestContext)) : null" />
+    </on-start>
+
+    <action-state id="Start">
+        <evaluate expression="'proceed'" />
+        <transition on="proceed" to="DoDiscovery" />
+    </action-state>
     
-    <view-state id="ExternalTransfer" view="externalRedirect:#{T(net.shibboleth.idp.authn.ExternalAuthentication).getExternalRedirect(flowRequestContext.getActiveFlow().getApplicationContext().getBean('shibboleth.authn.RemoteUser.externalAuthnPathStrategy').apply(opensamlProfileRequestContext), flowExecutionContext.getKey().toString())}">
+    <view-state id="PostDiscovery" view="externalRedirect:#{T(net.shibboleth.idp.authn.ExternalAuthentication).getExternalRedirect(flowRequestContext.getActiveFlow().getApplicationContext().getBean('shibboleth.authn.RemoteUser.externalAuthnPathStrategy').apply(opensamlProfileRequestContext), flowExecutionContext.getKey().toString())}">
         <attribute name="csrf_excluded" value="true" type="boolean"/>
         <on-render>
             <evaluate expression="opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext)).addSubcontext(new net.shibboleth.idp.authn.context.ExternalAuthenticationContext(new net.shibboleth.idp.authn.impl.ExternalAuthenticationImpl(calledAsExtendedFlow?:false)), true).setFlowExecutionUrl(flowExecutionUrl + '&_eventId_proceed=1')" />
diff --git a/idp-conf/src/main/resources/system/flows/authn/saml-authn-flow.xml b/idp-conf/src/main/resources/system/flows/authn/saml-authn-flow.xml
index 133aa5b..ea4b579 100644
--- a/idp-conf/src/main/resources/system/flows/authn/saml-authn-flow.xml
+++ b/idp-conf/src/main/resources/system/flows/authn/saml-authn-flow.xml
@@ -3,17 +3,17 @@
       xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow.xsd"
       parent="authn.abstract">
 
-    <!-- This is a login flow for oroxied authentication implemented via SAML 2.0. -->
+    <!-- This is a login flow for proxied authentication implemented via SAML 2.0. -->
 
     <on-start>
+        <!-- If installed, this can bypass discovery. -->
         <evaluate expression="flowRequestContext.getActiveFlow().getApplicationContext().containsBean('shibboleth.authn.SAML.discoveryFunction') ? opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext)).setAuthenticatingAuthority(flowRequestContext.getActiveFlow().getApplicationContext().getBean('shibboleth.authn.SAML.discoveryFunction').apply(opensamlProfileRequestContext)) : null" />
     </on-start>
 
-    <decision-state id="CheckDiscovery">
-        <if test="opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext)).getAttemptedFlow().isDiscoveryRequired()"
-            then="DoDiscovery"
-            else="PostDiscovery"/>
-    </decision-state>
+    <action-state id="Start">
+        <evaluate expression="'proceed'" />
+        <transition on="proceed" to="DoDiscovery" />
+    </action-state>
 
     <action-state id="PostDiscovery">
         <evaluate expression="InitializeProxyProfileRequestContext" />

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


More information about the commits mailing list