[java-identity-provider] branch main updated: IDP-1758 - Allow suppression of AuthenticatingAuthority elements
Scott Cantor
cantor.2 at osu.edu
Thu Jun 24 22:15:53 UTC 2021
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch main
in repository java-identity-provider.
View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=8a2f72edeff5c3a1180f412bdb67f93067745abe
The following commit(s) were added to refs/heads/main by this push:
new 8a2f72ede IDP-1758 - Allow suppression of AuthenticatingAuthority elements
8a2f72ede is described below
commit 8a2f72edeff5c3a1180f412bdb67f93067745abe
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Thu Jun 24 18:15:50 2021 -0400
IDP-1758 - Allow suppression of AuthenticatingAuthority elements
https://issues.shibboleth.net/jira/browse/IDP-1758
---
.../shibboleth/idp/conf/relying-party-mddriven.xml | 8 +++
.../config/BrowserSSOProfileConfiguration.java | 46 +++++++++++++++
.../SuppressAuthenticatingAuthorityPredicate.java | 49 ++++++++++++++++
.../profile/impl/AddAuthnStatementToAssertion.java | 68 ++++++++++++++++------
.../impl/AddAuthnStatementToAssertionTest.java | 25 +++++++-
5 files changed, 175 insertions(+), 21 deletions(-)
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/relying-party-mddriven.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/relying-party-mddriven.xml
index d098e6be7..8bb828a69 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/relying-party-mddriven.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/relying-party-mddriven.xml
@@ -421,6 +421,14 @@
<constructor-arg value="true" />
</bean>
</property>
+ <property name="suppressAuthenticatingAuthoritiesPredicate">
+ <bean class="net.shibboleth.utilities.java.support.logic.PredicateSupport" factory-method="fromFunction">
+ <constructor-arg>
+ <bean parent="shibboleth.MDDrivenBoolProperty" p:propertyName="suppressAuthenticatingAuthorities" />
+ </constructor-arg>
+ <constructor-arg value="false" />
+ </bean>
+ </property>
<property name="authnContextTranslationStrategyLookupStrategy">
<bean parent="shibboleth.MDDrivenBeanProperty" p:propertyName="authnContextTranslationStrategy"
p:propertyType="#{T(java.util.function.Function)}">
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/BrowserSSOProfileConfiguration.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/BrowserSSOProfileConfiguration.java
index 93d5d77de..89cca6aea 100644
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/BrowserSSOProfileConfiguration.java
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/BrowserSSOProfileConfiguration.java
@@ -44,6 +44,7 @@ import net.shibboleth.utilities.java.support.logic.FunctionSupport;
import net.shibboleth.utilities.java.support.primitive.StringSupport;
import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.saml.saml2.core.AuthenticatingAuthority;
import org.opensaml.saml.saml2.core.AuthnContext;
import org.opensaml.saml.saml2.core.AuthnContextComparisonTypeEnumeration;
import org.opensaml.saml.saml2.core.SubjectLocality;
@@ -87,6 +88,11 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML2ArtifactAwarePr
/** Whether authentication results should carry the proxied AuthnInstant. */
@Nonnull private Predicate<ProfileRequestContext> proxiedAuthnInstantPredicate;
+ /**
+ * The predicate used to determine whether to suppress {@link AuthenticatingAuthority} when possible.
+ */
+ @Nonnull private Predicate<ProfileRequestContext> suppressAuthenticatingAuthorityPredicate;
+
/** Lookup function to supply maximum session lifetime. */
@Nonnull private Function<ProfileRequestContext,Duration> maximumSPSessionLifetimeLookupStrategy;
@@ -146,6 +152,7 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML2ArtifactAwarePr
checkAddressPredicate = Predicates.alwaysTrue();
skipEndpointValidationWhenSignedPredicate = Predicates.alwaysFalse();
proxiedAuthnInstantPredicate = Predicates.alwaysTrue();
+ suppressAuthenticatingAuthorityPredicate = Predicates.alwaysFalse();
maximumSPSessionLifetimeLookupStrategy = FunctionSupport.constant(null);
maximumTimeSinceAuthnLookupStrategy = FunctionSupport.constant(null);
maximumTokenDelegationChainLengthLookupStrategy = FunctionSupport.constant(DEFAULT_DELEGATION_CHAIN_LENGTH);
@@ -356,6 +363,45 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML2ArtifactAwarePr
@Nonnull final Predicate<ProfileRequestContext> condition) {
skipEndpointValidationWhenSignedPredicate = Constraint.isNotNull(condition, "Condition cannot be null");
}
+
+ /**
+ * Gets whether to suppress inclusion of {@link AuthenticatingAuthority} element.
+ *
+ * <p>Defaults to false.</p>
+ *
+ * @param profileRequestContext current profile request context
+ *
+ * @return true iff the element should be suppressed when possible
+ *
+ * @since 4.2.0
+ */
+ public boolean isSuppressAuthenticatingAuthority(@Nullable final ProfileRequestContext profileRequestContext) {
+ return suppressAuthenticatingAuthorityPredicate.test(profileRequestContext);
+ }
+
+ /**
+ * Sets whether to suppress inclusion of {@link AuthenticatingAuthority} element.
+ *
+ * <p>Defaults to false.</p>
+ *
+ * @param flag flag to set
+ *
+ * @since 4.2.0
+ */
+ public void setSuppressAuthenticatingAuthority(final boolean flag) {
+ suppressAuthenticatingAuthorityPredicate = flag ? Predicates.alwaysTrue() : Predicates.alwaysFalse();
+ }
+
+ /**
+ * Sets condition to determine whether to suppress inclusion of {@link AuthenticatingAuthority} element.
+ *
+ * @param condition condition to set
+ *
+ * @since 4.2.0
+ */
+ public void setSuppressAuthenticatingAuthority(@Nonnull final Predicate<ProfileRequestContext> condition) {
+ suppressAuthenticatingAuthorityPredicate = Constraint.isNotNull(condition, "Condition cannot be null");
+ }
/**
* Gets whether authentication results produced by use of this profile should carry the proxied
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/logic/SuppressAuthenticatingAuthorityPredicate.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/logic/SuppressAuthenticatingAuthorityPredicate.java
new file mode 100644
index 000000000..9d8e2c8ec
--- /dev/null
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/logic/SuppressAuthenticatingAuthorityPredicate.java
@@ -0,0 +1,49 @@
+/*
+ * 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.saml2.profile.config.logic;
+
+import javax.annotation.Nullable;
+
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
+import net.shibboleth.idp.profile.logic.AbstractRelyingPartyPredicate;
+import net.shibboleth.idp.saml.saml2.profile.config.BrowserSSOProfileConfiguration;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+/**
+ * A predicate that evaluates a {@link ProfileRequestContext} and extracts the effective
+ * setting of {@link BrowserSSOProfileConfiguration#isSuppressAuthenticatingAuthority(ProfileRequestContext)}.
+ *
+ * <p>Defaults to false.</p>
+ *
+ * @since 4.2.0
+ */
+public class SuppressAuthenticatingAuthorityPredicate extends AbstractRelyingPartyPredicate {
+
+ /** {@inheritDoc} */
+ public boolean test(@Nullable final ProfileRequestContext input) {
+
+ final RelyingPartyContext rpc = getRelyingPartyContextLookupStrategy().apply(input);
+ if (rpc != null && rpc.getProfileConfig() instanceof BrowserSSOProfileConfiguration) {
+ return ((BrowserSSOProfileConfiguration) rpc.getProfileConfig()).isSuppressAuthenticatingAuthority(input);
+ }
+
+ return false;
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertion.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertion.java
index 581848ddb..43da3bef2 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertion.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertion.java
@@ -22,6 +22,7 @@ import java.time.Duration;
import java.time.Instant;
import java.util.Set;
import java.util.function.Function;
+import java.util.function.Predicate;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -39,6 +40,7 @@ import net.shibboleth.idp.saml.authn.principal.AuthnContextClassRefPrincipal;
import net.shibboleth.idp.saml.authn.principal.AuthnContextDeclRefPrincipal;
import net.shibboleth.idp.saml.profile.config.navigate.SessionLifetimeLookupFunction;
import net.shibboleth.idp.saml.profile.impl.BaseAddAuthenticationStatementToAssertion;
+import net.shibboleth.idp.saml.saml2.profile.config.logic.SuppressAuthenticatingAuthorityPredicate;
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;
@@ -94,10 +96,14 @@ public class AddAuthnStatementToAssertion extends BaseAddAuthenticationStatement
/** Strategy used to determine SessionNotOnOrAfter value to set. */
@Nullable private Function<ProfileRequestContext,Duration> sessionLifetimeLookupStrategy;
+
+ /** Strategy used to determine whether to suppress AuthenticatingAuthority. */
+ @Nonnull private Predicate<ProfileRequestContext> suppressAuthenticatingAuthorityPredicate;
/** Constructor. */
public AddAuthnStatementToAssertion() {
sessionLifetimeLookupStrategy = new SessionLifetimeLookupFunction();
+ suppressAuthenticatingAuthorityPredicate = new SuppressAuthenticatingAuthorityPredicate();
}
/**
@@ -135,6 +141,18 @@ public class AddAuthnStatementToAssertion extends BaseAddAuthenticationStatement
sessionLifetimeLookupStrategy = strategy;
}
+ /**
+ * Set the condition used to determine whether to suppress inclusion of AuthenticatingAuthority.
+ *
+ * @param condition condition to set
+ */
+ public void setSuppressAuthenticatingAuthorityPredicate(
+ @Nonnull final Predicate<ProfileRequestContext> condition) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ suppressAuthenticatingAuthorityPredicate = Constraint.isNotNull(condition, "Condition cannot be null");
+ }
+
/** {@inheritDoc} */
@Override
protected void doInitialize() throws ComponentInitializationException {
@@ -169,7 +187,6 @@ public class AddAuthnStatementToAssertion extends BaseAddAuthenticationStatement
log.debug("{} Added AuthenticationStatement to Assertion {}", getLogPrefix(), assertion.getID());
}
-// Checkstyle: CyclomaticComplexity OFF
/**
* Build the {@link AuthnStatement} to be added to the {@link Response}.
*
@@ -212,23 +229,7 @@ public class AddAuthnStatementToAssertion extends BaseAddAuthenticationStatement
classRefLookupStrategy.apply(profileRequestContext).getAuthnContextClassRef());
}
- final Set<ProxyAuthenticationPrincipal> proxyPrincipals =
- getAuthenticationResult().getSubject().getPrincipals(ProxyAuthenticationPrincipal.class);
- if (proxyPrincipals != null && !proxyPrincipals.isEmpty()) {
- if (proxyPrincipals.size() == 1) {
- final SAMLObjectBuilder<AuthenticatingAuthority> authorityBuilder =
- (SAMLObjectBuilder<AuthenticatingAuthority>) bf.<AuthenticatingAuthority>getBuilderOrThrow(
- AuthenticatingAuthority.DEFAULT_ELEMENT_NAME);
- for (final String authority : proxyPrincipals.iterator().next().getAuthorities()) {
- final AuthenticatingAuthority aa = authorityBuilder.buildObject();
- aa.setURI(authority);
- authnContext.getAuthenticatingAuthorities().add(aa);
- }
- } else {
- log.warn("{} Multiple ProxyAuthenticationPrincipals, skipping AuthenticatingAuthority population",
- getLogPrefix());
- }
- }
+ addAuthenticatingAuthorities(profileRequestContext, authnContext);
final Duration lifetime = sessionLifetimeLookupStrategy != null ?
sessionLifetimeLookupStrategy.apply(profileRequestContext) : null;
@@ -249,7 +250,36 @@ public class AddAuthnStatementToAssertion extends BaseAddAuthenticationStatement
return statement;
}
-// Checkstyle: CyclomaticComplexity ON
+
+ private void addAuthenticatingAuthorities(@Nonnull final ProfileRequestContext profileRequestContext,
+ @Nonnull final AuthnContext authnContext) {
+
+ final Set<ProxyAuthenticationPrincipal> proxyPrincipals =
+ getAuthenticationResult().getSubject().getPrincipals(ProxyAuthenticationPrincipal.class);
+ if (proxyPrincipals != null && !proxyPrincipals.isEmpty()) {
+ if (proxyPrincipals.size() == 1) {
+ final ProxyAuthenticationPrincipal proxyPrincipal = proxyPrincipals.iterator().next();
+
+ final boolean suppress = suppressAuthenticatingAuthorityPredicate.test(profileRequestContext);
+ if (!suppress) {
+ final SAMLObjectBuilder<AuthenticatingAuthority> authorityBuilder =
+ (SAMLObjectBuilder<AuthenticatingAuthority>) XMLObjectProviderRegistrySupport
+ .getBuilderFactory().<AuthenticatingAuthority>getBuilderOrThrow(
+ AuthenticatingAuthority.DEFAULT_ELEMENT_NAME);
+ for (final String authority : proxyPrincipal.getAuthorities()) {
+ final AuthenticatingAuthority aa = authorityBuilder.buildObject();
+ aa.setURI(authority);
+ authnContext.getAuthenticatingAuthorities().add(aa);
+ }
+ } else {
+ log.debug("{} Suppressing AuthenticatingAuthority population", getLogPrefix());
+ }
+ } else {
+ log.warn("{} Multiple ProxyAuthenticationPrincipals, skipping AuthenticatingAuthority population",
+ getLogPrefix());
+ }
+ }
+ }
/**
* Default strategy for obtaining assertion to modify.
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertionTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertionTest.java
index dbb767b36..af300e935 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertionTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAuthnStatementToAssertionTest.java
@@ -19,7 +19,7 @@ package net.shibboleth.idp.saml.saml2.profile.impl;
import java.time.Duration;
import java.time.Instant;
-import java.util.Arrays;
+import java.util.List;
import javax.security.auth.Subject;
@@ -58,6 +58,7 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/** {@link AddAuthnStatementToAssertion} unit test. */
+ at SuppressWarnings("javadoc")
public class AddAuthnStatementToAssertionTest extends OpenSAMLInitBaseTestCase {
private RequestContext rc;
@@ -221,7 +222,7 @@ public class AddAuthnStatementToAssertionTest extends OpenSAMLInitBaseTestCase {
@Test public void testAuthenticatingAuthorities() {
prc.getSubcontext(AuthenticationContext.class, true).setAuthenticationResult(
- new AuthenticationResult("Test", new ProxyAuthenticationPrincipal(Arrays.asList("foo", "bar", "baz"))));
+ new AuthenticationResult("Test", new ProxyAuthenticationPrincipal(List.of("foo", "bar", "baz"))));
final Event event = action.execute(rc);
ActionTestingSupport.assertProceedEvent(event);
@@ -237,4 +238,24 @@ public class AddAuthnStatementToAssertionTest extends OpenSAMLInitBaseTestCase {
Assert.assertEquals(authnContext.getAuthenticatingAuthorities().get(2).getURI(), "baz");
}
+ @Test public void testSuppressedAuthenticatingAuthorities() {
+ final BrowserSSOProfileConfiguration ssoConfig = new BrowserSSOProfileConfiguration();
+ ssoConfig.setSuppressAuthenticatingAuthority(true);
+ ssoConfig.setSecurityConfiguration(new SecurityConfiguration());
+ prc.getSubcontext(RelyingPartyContext.class).setProfileConfig(ssoConfig);
+
+ prc.getSubcontext(AuthenticationContext.class, true).setAuthenticationResult(
+ new AuthenticationResult("Test", new ProxyAuthenticationPrincipal(List.of("foo", "bar", "baz"))));
+
+ final Event event = action.execute(rc);
+ ActionTestingSupport.assertProceedEvent(event);
+
+ final Response response = (Response) prc.getOutboundMessageContext().getMessage();
+ final Assertion assertion = response.getAssertions().get(0);
+ final AuthnStatement authenticationStatement = assertion.getAuthnStatements().get(0);
+ final AuthnContext authnContext = authenticationStatement.getAuthnContext();
+ Assert.assertNotNull(authnContext);
+ Assert.assertTrue(authnContext.getAuthenticatingAuthorities().isEmpty());
+ }
+
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list