[java-identity-provider COMMIT] in /trunk/idp-authn-impl/src: main/java/net/shibboleth/idp/authn/impl/SelectAuthentic...

noreply at shibboleth.net noreply at shibboleth.net
Mon Nov 4 21:47:18 EST 2013


Author: scantor
Date: Mon Nov  4 21:47:18 2013
New Revision: 4932

URL: http://svn.shibboleth.net/view/java-identity-provider?rev=4932&view=rev
Log:
Implement a "history" of flows to allow selection to loop back after a flow fails.

Modified:
    trunk/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/SelectAuthenticationFlow.java
    trunk/idp-authn-impl/src/test/java/net/shibboleth/idp/authn/impl/SelectAuthenticationFlowTest.java

Modified: trunk/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/SelectAuthenticationFlow.java
URL: http://svn.shibboleth.net/view/java-identity-provider/trunk/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/SelectAuthenticationFlow.java?rev=4932&r1=4931&r2=4932&view=diff
==============================================================================
--- trunk/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/SelectAuthenticationFlow.java (original)
+++ trunk/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/SelectAuthenticationFlow.java Mon Nov  4 21:47:18 2013
@@ -105,6 +105,14 @@
             @Nonnull final AuthenticationContext authenticationContext) throws AuthenticationException {
         
         requestedPrincipalCtx = authenticationContext.getSubcontext(RequestedPrincipalContext.class, false);
+        
+        // Detect a previous attempted flow, and move it to the intermediate collection.
+        // This will prevent re-selecting the same (probably failed) flow again.
+        if (authenticationContext.getAttemptedFlow() != null) {
+            authenticationContext.getIntermediateFlows().put(
+                    authenticationContext.getAttemptedFlow().getId(), authenticationContext.getAttemptedFlow());
+        }
+        
         return true;
     }
     
@@ -132,27 +140,44 @@
         
         if (authenticationContext.isForceAuthn()) {
             log.debug("{} forced authentication requested, selecting an inactive flow", getLogPrefix());
-            if (authenticationContext.getPotentialFlows().isEmpty()) {
-                log.error("{} no potential flows to choose from, authentication will fail", getLogPrefix());
+            AuthenticationFlowDescriptor flow = getUnattemptedInactiveFlow(authenticationContext);
+            if (flow == null) {
+                log.error("{} no potential flows left to choose from, authentication will fail", getLogPrefix());
                 ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.NO_POTENTIAL_FLOW);
                 return;
             }
-            selectInactiveFlow(profileRequestContext, authenticationContext,
-                    authenticationContext.getPotentialFlows().values().iterator().next());
+            selectInactiveFlow(profileRequestContext, authenticationContext, flow);
         } else if (authenticationContext.getActiveResults().isEmpty()) {
             log.debug("{} no active results available, selecting an inactive flow", getLogPrefix());
-            if (authenticationContext.getPotentialFlows().isEmpty()) {
-                log.error("{} no potential flows to choose from, authentication will fail", getLogPrefix());
+            AuthenticationFlowDescriptor flow = getUnattemptedInactiveFlow(authenticationContext);
+            if (flow == null) {
+                log.error("{} no potential flows left to choose from, authentication will fail", getLogPrefix());
                 ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.NO_POTENTIAL_FLOW);
                 return;
             }
-            selectInactiveFlow(profileRequestContext, authenticationContext,
-                    authenticationContext.getPotentialFlows().values().iterator().next());
+            selectInactiveFlow(profileRequestContext, authenticationContext, flow);
         } else {
             // Pick a result to reuse.
             selectActiveResult(profileRequestContext, authenticationContext,
                     authenticationContext.getActiveResults().values().iterator().next());
         }
+    }
+
+    /**
+     * Return the first inactive potential flow not found in the intermediate flows collection. 
+     * 
+     * @param authenticationContext the current authentication context
+     * @return an eligible flow, or null
+     */
+    @Nullable private AuthenticationFlowDescriptor getUnattemptedInactiveFlow(
+            @Nonnull final AuthenticationContext authenticationContext) {
+        for (AuthenticationFlowDescriptor flow : authenticationContext.getPotentialFlows().values()) {
+            if (!authenticationContext.getIntermediateFlows().containsKey(flow.getId())) {
+                return flow;
+            }
+        }
+        
+        return null;
     }
 
     /**
@@ -224,6 +249,7 @@
         Map<String,AuthenticationFlowDescriptor> potentialFlows = authenticationContext.getPotentialFlows();
         
         // Check each flow for compatibility with request. Don't check for an active result also.
+        // Also omit anything in the intermediates collection already.

[... 86 lines stripped ...]


More information about the commits mailing list