[java-identity-provider] branch master updated: Route "weighted" Principal determination through flow descriptors.
Scott Cantor
cantor.2 at osu.edu
Mon Jan 14 16:39:50 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=a07ea60f2657676d6604fd2f8bf258e73870c063
The following commit(s) were added to refs/heads/master by this push:
new a07ea60 Route "weighted" Principal determination through flow descriptors.
a07ea60 is described below
commit a07ea60f2657676d6604fd2f8bf258e73870c063
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Mon Jan 14 16:39:47 2019 -0500
Route "weighted" Principal determination through flow descriptors.
---
.../idp/authn/AuthenticationFlowDescriptor.java | 72 +++++++++++++++++++-
.../DefaultPrincipalDeterminationStrategy.java | 68 +++----------------
.../idp/authn/impl/FinalizeAuthentication.java | 76 ++++------------------
.../resources/system/conf/general-authn-system.xml | 3 +-
.../resources/system/flows/authn/authn-beans.xml | 3 +-
.../system/flows/saml/saml1/common-beans.xml | 3 +-
.../system/flows/saml/saml2/common-beans.xml | 3 +-
7 files changed, 98 insertions(+), 130 deletions(-)
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/AuthenticationFlowDescriptor.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/AuthenticationFlowDescriptor.java
index ba54709..fe18087 100644
--- a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/AuthenticationFlowDescriptor.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/AuthenticationFlowDescriptor.java
@@ -19,7 +19,11 @@ package net.shibboleth.idp.authn;
import java.io.IOException;
import java.security.Principal;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
@@ -95,6 +99,9 @@ public class AuthenticationFlowDescriptor extends AbstractIdentifiableInitializa
/** Custom serializer for the results generated by this flow. */
@Nullable private StorageSerializer<AuthenticationResult> resultSerializer;
+
+ /** Weighted sort oredering of custom Principals produced by flow(s). */
+ @Nullable @NonnullElements private Map<Principal,Integer> principalWeightMap;
/** Constructor. */
public AuthenticationFlowDescriptor() {
@@ -103,6 +110,7 @@ public class AuthenticationFlowDescriptor extends AbstractIdentifiableInitializa
supportedPrincipals = new Subject();
activationCondition = Predicates.alwaysTrue();
inactivityTimeout = 30 * 60 * 1000;
+ principalWeightMap = Collections.emptyMap();
}
/**
@@ -317,6 +325,23 @@ public class AuthenticationFlowDescriptor extends AbstractIdentifiableInitializa
resultSerializer = Constraint.isNotNull(serializer, "StorageSerializer cannot be null");
}
+
+ /**
+ * Set the map of Principals to weight values to impose a sort order on any matching Principals
+ * found in the authentication result.
+ *
+ * <p>This was moved from a stand-alone bean into the descriptor beans in order to eliminate
+ * stand-alone beans from the flow descriptor configuration files(s).</p>
+ *
+ * @param map map to set
+ *
+ * @since 4.0.0
+ */
+ public void setPrincipalWeightMap(@Nullable @NonnullElements final Map<Principal,Integer> map) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ principalWeightMap = map != null ? map : Collections.emptyMap();
+ }
/** {@inheritDoc} */
@Override protected void doInitialize() throws ComponentInitializationException {
@@ -347,6 +372,28 @@ public class AuthenticationFlowDescriptor extends AbstractIdentifiableInitializa
- inactivityTimeout - STORAGE_EXPIRATION_OFFSET : null);
}
+ /**
+ * Apply the current weighted map to find the highest-weighted object amongst the inputs.
+ *
+ * @param <T> principal type
+ * @param principals input collection
+ * @return the highest weighted as governed by the map set via {@link #setPrincipalWeightMap(Map)}
+ *
+ * @since 4.0.0
+ */
+ @Nullable public <T extends Principal> T getHighestWeighted(
+ @Nonnull @NonnullElements final Collection<T> principals) {
+ if (principals.isEmpty()) {
+ return null;
+ } else if (principalWeightMap.isEmpty() || principals.size() == 1) {
+ return principals.iterator().next();
+ } else {
+ final Object[] principalArray = principals.toArray();
+ Arrays.sort(principalArray, new WeightedComparator());
+ return (T) principalArray[principalArray.length - 1];
+ }
+ }
+
/** {@inheritDoc} */
@Override public int hashCode() {
return getId().hashCode();
@@ -375,7 +422,30 @@ public class AuthenticationFlowDescriptor extends AbstractIdentifiableInitializa
.add("supportsForcedAuthentication", supportsForced)
.add("lifetime", lifetime).add("inactivityTimeout", inactivityTimeout).toString();
}
-
+
+ /**
+ * A {@link Comparator} that compares the mapped weights of the two operands, using a weight of zero
+ * for any unmapped values.
+ */
+ private class WeightedComparator implements Comparator {
+
+ /** {@inheritDoc} */
+ @Override
+ public int compare(final Object o1, final Object o2) {
+
+ final int weight1 = principalWeightMap.containsKey(o1) ? principalWeightMap.get(o1) : 0;
+ final int weight2 = principalWeightMap.containsKey(o2) ? principalWeightMap.get(o2) : 0;
+ if (weight1 < weight2) {
+ return -1;
+ } else if (weight1 > weight2) {
+ return 1;
+ }
+
+ return 0;
+ }
+
+ }
+
static {
STORAGE_EXPIRATION_OFFSET = 10 * 60 * 1000;
}
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/principal/DefaultPrincipalDeterminationStrategy.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/principal/DefaultPrincipalDeterminationStrategy.java
index 149d166..70bbb40 100644
--- a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/principal/DefaultPrincipalDeterminationStrategy.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/principal/DefaultPrincipalDeterminationStrategy.java
@@ -18,19 +18,14 @@
package net.shibboleth.idp.authn.principal;
import java.security.Principal;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import net.shibboleth.idp.authn.AuthenticationFlowDescriptor;
import net.shibboleth.idp.authn.context.AuthenticationContext;
import net.shibboleth.utilities.java.support.annotation.ParameterName;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
import net.shibboleth.utilities.java.support.logic.Constraint;
import org.opensaml.messaging.context.navigate.ChildContextLookup;
@@ -60,9 +55,6 @@ public class DefaultPrincipalDeterminationStrategy<T extends Principal> implemen
/** Default Principal to return. */
@Nonnull private final T defaultPrincipal;
-
- /** A map supplying weighted preference to particular Principals. */
- @Nonnull @NonnullElements private Map<T,Integer> weightMap;
/** Authentication context lookup strategy. */
@Nonnull private Function<ProfileRequestContext,AuthenticationContext> authnContextLookupStrategy;
@@ -77,29 +69,8 @@ public class DefaultPrincipalDeterminationStrategy<T extends Principal> implemen
@Nonnull @ParameterName(name="principal") final T principal) {
principalType = Constraint.isNotNull(type, "Class type cannot be null");
defaultPrincipal = Constraint.isNotNull(principal, "Default Principal cannot be null");
- weightMap = Collections.emptyMap();
authnContextLookupStrategy = new ChildContextLookup<>(AuthenticationContext.class, false);
}
-
- /**
- * Set the map of Principals to weight values to impose a sort order on any matching Principals
- * found in the authentication result.
- *
- * @param map map to set
- */
- public void setWeightMap(@Nullable @NonnullElements final Map<T,Integer> map) {
- if (map == null) {
- weightMap = Collections.emptyMap();
- return;
- }
-
- weightMap = new HashMap<>(map.size());
- for (final Map.Entry<T,Integer> entry : map.entrySet()) {
- if (entry.getKey() != null && entry.getValue() != null) {
- weightMap.put(entry.getKey(), entry.getValue());
- }
- }
- }
/**
* Set lookup strategy for {@link AuthenticationContext}.
@@ -117,40 +88,19 @@ public class DefaultPrincipalDeterminationStrategy<T extends Principal> implemen
if (ac == null || ac.getAuthenticationResult() == null) {
return defaultPrincipal;
}
+
+ final AuthenticationFlowDescriptor descriptor = ac.getAvailableFlows().get(
+ ac.getAuthenticationResult().getAuthenticationFlowId());
+ if (descriptor == null) {
+ return defaultPrincipal;
+ }
final Set<T> principals = ac.getAuthenticationResult().getSupportedPrincipals(principalType);
if (principals.isEmpty()) {
return defaultPrincipal;
- } else if (principals.size() == 1 || weightMap.isEmpty()) {
- return principals.iterator().next();
+ } else {
+ return descriptor.getHighestWeighted(principals);
}
-
- final Object[] principalArray = principals.toArray();
- Arrays.sort(principalArray, new WeightedComparator());
- return (T) principalArray[principalArray.length - 1];
- }
-
- /**
- * A {@link Comparator} that compares the mapped weights of the two operands, using a weight of zero
- * for any unmapped values.
- */
- private class WeightedComparator implements Comparator {
-
- /** {@inheritDoc} */
- @Override
- public int compare(final Object o1, final Object o2) {
-
- final int weight1 = weightMap.containsKey(o1) ? weightMap.get(o1) : 0;
- final int weight2 = weightMap.containsKey(o2) ? weightMap.get(o2) : 0;
- if (weight1 < weight2) {
- return -1;
- } else if (weight1 > weight2) {
- return 1;
- }
-
- return 0;
- }
-
}
}
\ No newline at end of file
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/FinalizeAuthentication.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/FinalizeAuthentication.java
index ae0d449..30c5f8b 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/FinalizeAuthentication.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/FinalizeAuthentication.java
@@ -19,10 +19,7 @@ package net.shibboleth.idp.authn.impl;
import java.security.Principal;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@@ -30,6 +27,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.shibboleth.idp.authn.AbstractAuthenticationAction;
+import net.shibboleth.idp.authn.AuthenticationFlowDescriptor;
import net.shibboleth.idp.authn.AuthenticationResult;
import net.shibboleth.idp.authn.AuthnEventIds;
import net.shibboleth.idp.authn.context.AuthenticationContext;
@@ -41,7 +39,6 @@ import net.shibboleth.idp.authn.principal.PrincipalEvalPredicateFactory;
import net.shibboleth.idp.authn.principal.PrincipalSupportingComponent;
import net.shibboleth.idp.profile.IdPEventIds;
import net.shibboleth.idp.session.context.SessionContext;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
import org.opensaml.profile.action.ActionSupport;
import org.opensaml.profile.context.ProfileRequestContext;
@@ -94,41 +91,18 @@ public class FinalizeAuthentication extends AbstractAuthenticationAction {
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(FinalizeAuthentication.class);
- /** A map supplying weighted preference to particular Principals. */
- @Nonnull @NonnullElements private Map<Principal,Integer> weightMap;
-
/** The principal name extracted from the context tree. */
@Nullable private String canonicalPrincipalName;
-
- /** Constructor. */
- public FinalizeAuthentication() {
- weightMap = Collections.emptyMap();
- }
-
- /**
- * Set the map of Principals to weight values to impose a sort order on any matching Principals
- * found in the authentication result.
- *
- * @param map map to set
- */
- public void setWeightMap(@Nullable @NonnullElements final Map<Principal,Integer> map) {
- if (map == null) {
- weightMap = Collections.emptyMap();
- return;
- }
- weightMap = new HashMap<>(map.size());
- for (final Map.Entry<Principal,Integer> entry : map.entrySet()) {
- if (entry.getKey() != null && entry.getValue() != null) {
- weightMap.put(entry.getKey(), entry.getValue());
- }
- }
- }
-
+// Checkstyle: CyclomaticComplexity OFF
/** {@inheritDoc} */
@Override
protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext,
@Nonnull final AuthenticationContext authenticationContext) {
+
+ if (!super.doPreExecute(profileRequestContext, authenticationContext)) {
+ return false;
+ }
final SubjectCanonicalizationContext c14nCtx =
profileRequestContext.getSubcontext(SubjectCanonicalizationContext.class);
@@ -188,8 +162,9 @@ public class FinalizeAuthentication extends AbstractAuthenticationAction {
getLogPrefix());
}
- return super.doPreExecute(profileRequestContext, authenticationContext);
+ return true;
}
+// Checkstyle: CyclomaticComplexity ON
/** {@inheritDoc} */
@Override
@@ -226,7 +201,7 @@ public class FinalizeAuthentication extends AbstractAuthenticationAction {
* result that satisfies the request criteria.
*
* <p>If a weighting map is supplied, the {@link Principal} returned is the one that both satisfies
- * the request and is highest weighted.</p>
+ * the request and is highest weighted according to the underlying flow descriptor.</p>
*
* @param authenticationContext authentication context
* @param requestedPrincipalCtx request criteria
@@ -235,7 +210,7 @@ public class FinalizeAuthentication extends AbstractAuthenticationAction {
*/
@Nullable protected Principal findMatchingPrincipal(@Nonnull final AuthenticationContext authenticationContext,
@Nonnull final RequestedPrincipalContext requestedPrincipalCtx) {
-
+
// Maintain a list of each Principal that matches the request.
final ArrayList<Principal> matches = new ArrayList<>();
@@ -280,36 +255,11 @@ public class FinalizeAuthentication extends AbstractAuthenticationAction {
if (matches.isEmpty()) {
return null;
- } else if (matches.size() == 1 || weightMap.isEmpty()) {
- return matches.get(0);
} else {
- final Object[] principalArray = matches.toArray();
- Arrays.sort(principalArray, new WeightedComparator());
- return (Principal) principalArray[principalArray.length - 1];
+ final AuthenticationFlowDescriptor flowDescriptor = authenticationContext.getAvailableFlows().get(
+ authenticationContext.getAuthenticationResult().getAuthenticationFlowId());
+ return flowDescriptor.getHighestWeighted(matches);
}
}
-
- /**
- * A {@link Comparator} that compares the mapped weights of the two operands, using a weight of zero
- * for any unmapped values.
- */
- private class WeightedComparator implements Comparator {
-
- /** {@inheritDoc} */
- @Override
- public int compare(final Object o1, final Object o2) {
-
- final int weight1 = weightMap.containsKey(o1) ? weightMap.get(o1) : 0;
- final int weight2 = weightMap.containsKey(o2) ? weightMap.get(o2) : 0;
- if (weight1 < weight2) {
- return -1;
- } else if (weight1 > weight2) {
- return 1;
- }
-
- return 0;
- }
-
- }
}
\ No newline at end of file
diff --git a/idp-conf/src/main/resources/system/conf/general-authn-system.xml b/idp-conf/src/main/resources/system/conf/general-authn-system.xml
index 47d7d52..b485916 100644
--- a/idp-conf/src/main/resources/system/conf/general-authn-system.xml
+++ b/idp-conf/src/main/resources/system/conf/general-authn-system.xml
@@ -33,7 +33,8 @@
p:forcedAuthenticationSupported="false"
p:nonBrowserSupported="true"
p:lifetime="%{idp.authn.defaultLifetime:PT60M}"
- p:inactivityTimeout="%{idp.authn.defaultTimeout:PT30M}">
+ p:inactivityTimeout="%{idp.authn.defaultTimeout:PT30M}"
+ p:principalWeightMap="#{getObject('shibboleth.AuthenticationPrincipalWeightMap')}">
<property name="supportedPrincipals">
<list>
<bean parent="shibboleth.SAML2AuthnContextClassRef"
diff --git a/idp-conf/src/main/resources/system/flows/authn/authn-beans.xml b/idp-conf/src/main/resources/system/flows/authn/authn-beans.xml
index 578e8f5..dfc0658 100644
--- a/idp-conf/src/main/resources/system/flows/authn/authn-beans.xml
+++ b/idp-conf/src/main/resources/system/flows/authn/authn-beans.xml
@@ -104,8 +104,7 @@
</bean>
<bean id="FinalizeAuthentication"
- class="net.shibboleth.idp.authn.impl.FinalizeAuthentication" scope="prototype"
- p:weightMap="#{getObject('shibboleth.AuthenticationPrincipalWeightMap')}" />
+ class="net.shibboleth.idp.authn.impl.FinalizeAuthentication" scope="prototype" />
<bean id="UpdateSessionWithAuthenticationResult"
class="net.shibboleth.idp.session.impl.UpdateSessionWithAuthenticationResult" scope="prototype"
diff --git a/idp-conf/src/main/resources/system/flows/saml/saml1/common-beans.xml b/idp-conf/src/main/resources/system/flows/saml/saml1/common-beans.xml
index 763fcca..9e74e4e 100644
--- a/idp-conf/src/main/resources/system/flows/saml/saml1/common-beans.xml
+++ b/idp-conf/src/main/resources/system/flows/saml/saml1/common-beans.xml
@@ -38,8 +38,7 @@
</property>
<property name="authenticationMethodLookupStrategy">
<bean class="net.shibboleth.idp.authn.principal.DefaultPrincipalDeterminationStrategy"
- c:type="net.shibboleth.idp.saml.authn.principal.AuthenticationMethodPrincipal"
- p:weightMap="#{getObject('shibboleth.AuthenticationPrincipalWeightMap')}">
+ c:type="net.shibboleth.idp.saml.authn.principal.AuthenticationMethodPrincipal">
<constructor-arg name="principal">
<bean class="net.shibboleth.idp.saml.authn.principal.AuthenticationMethodPrincipal"
c:method="#{T(org.opensaml.saml.saml1.core.AuthenticationStatement).UNSPECIFIED_AUTHN_METHOD}" />
diff --git a/idp-conf/src/main/resources/system/flows/saml/saml2/common-beans.xml b/idp-conf/src/main/resources/system/flows/saml/saml2/common-beans.xml
index 1c212ef..5119d23 100644
--- a/idp-conf/src/main/resources/system/flows/saml/saml2/common-beans.xml
+++ b/idp-conf/src/main/resources/system/flows/saml/saml2/common-beans.xml
@@ -39,8 +39,7 @@
</property>
<property name="classRefLookupStrategy">
<bean class="net.shibboleth.idp.authn.principal.DefaultPrincipalDeterminationStrategy"
- c:type="net.shibboleth.idp.saml.authn.principal.AuthnContextClassRefPrincipal"
- p:weightMap="#{getObject('shibboleth.AuthenticationPrincipalWeightMap')}">
+ c:type="net.shibboleth.idp.saml.authn.principal.AuthnContextClassRefPrincipal">
<constructor-arg name="principal">
<bean class="net.shibboleth.idp.saml.authn.principal.AuthnContextClassRefPrincipal"
c:classRef="#{T(org.opensaml.saml.saml2.core.AuthnContext).UNSPECIFIED_AUTHN_CTX}" />
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list