[java-identity-provider] branch main updated: IDP-2428 - AACLI does not dump encoded attributes with --unfiltered
Codeberg
noreply at shibboleth.net
Mon Apr 6 23:40:37 UTC 2026
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch main
in repository java-identity-provider.
View the commit online:
https://codeberg.org/Shibboleth/java-identity-provider/commit/a3dab7ea4e21adaff802f2ff280fd2da852368cc
The following commit(s) were added to refs/heads/main by this push:
new a3dab7ea4 IDP-2428 - AACLI does not dump encoded attributes with --unfiltered
a3dab7ea4 is described below
commit a3dab7ea4e21adaff802f2ff280fd2da852368cc
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Mon Apr 6 19:40:21 2026 -0400
IDP-2428 - AACLI does not dump encoded attributes with --unfiltered
https://shibboleth.atlassian.net/browse/IDP-2428
---
.../shibboleth/idp/cli/ResolverTestArguments.java | 47 +++++++++-------------
.../idp/flows/admin/resolvertest-beans.xml | 8 +++-
.../impl/ResolverTestUnfilteredPredicate.java | 46 +++++++++++++++++++++
.../impl/BaseAddAttributeStatementToAssertion.java | 32 +++++++++++++--
.../impl/AddAttributeStatementToAssertion.java | 4 +-
.../impl/AddAttributeStatementToAssertion.java | 4 +-
6 files changed, 103 insertions(+), 38 deletions(-)
diff --git a/idp-cli/src/main/java/net/shibboleth/idp/cli/ResolverTestArguments.java b/idp-cli/src/main/java/net/shibboleth/idp/cli/ResolverTestArguments.java
index 01ae4ab9d..1511ffc89 100644
--- a/idp-cli/src/main/java/net/shibboleth/idp/cli/ResolverTestArguments.java
+++ b/idp-cli/src/main/java/net/shibboleth/idp/cli/ResolverTestArguments.java
@@ -14,8 +14,8 @@
package net.shibboleth.idp.cli;
-import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -85,23 +85,14 @@ public class ResolverTestArguments extends AbstractCommandLineArguments {
if (saml1) {
if (saml2 || protocol != null) {
throw new IllegalArgumentException("The saml1, saml2, and protocol options are mutually exclusive");
- } else if (unfiltered) {
- throw new IllegalArgumentException(
- "The unfiltered option is mutually exclusive with the protocol options");
}
} else if (saml2) {
if (saml1 || protocol != null) {
throw new IllegalArgumentException("The saml1, saml2, and protocol options are mutually exclusive");
- } else if (unfiltered) {
- throw new IllegalArgumentException(
- "The unfiltered option is mutually exclusive with the protocol options");
}
} else if (protocol != null) {
if (saml1 || saml2) {
throw new IllegalArgumentException("The saml1, saml2, and protocol options are mutually exclusive");
- } else if (unfiltered) {
- throw new IllegalArgumentException(
- "The unfiltered option is mutually exclusive with the protocol options");
}
}
}
@@ -121,24 +112,24 @@ public class ResolverTestArguments extends AbstractCommandLineArguments {
builder.append('?');
}
- try {
- builder.append("requester=").append(URLEncoder.encode(requester, "UTF-8"));
- builder.append("&principal=").append(URLEncoder.encode(principal, "UTF-8"));
- final Integer idx = index;
- if (idx != null) {
- builder.append("&acsIndex").append(idx.toString());
- }
- if (saml1) {
- builder.append("&saml1");
- } else if (saml2) {
- builder.append("&saml2");
- } else if (protocol != null) {
- builder.append("&protocol=").append(URLEncoder.encode(protocol, "UTF-8"));
- } else if (unfiltered) {
- builder.append("&unfiltered");
- }
- } catch (final UnsupportedEncodingException e) {
- // UTF-8 is a required encoding.
+ builder.append("requester=").append(URLEncoder.encode(requester, StandardCharsets.UTF_8));
+ builder.append("&principal=").append(URLEncoder.encode(principal, StandardCharsets.UTF_8));
+
+ final Integer idx = index;
+ if (idx != null) {
+ builder.append("&acsIndex").append(idx.toString());
+ }
+
+ if (unfiltered) {
+ builder.append("&unfiltered");
+ }
+
+ if (saml1) {
+ builder.append("&saml1");
+ } else if (saml2) {
+ builder.append("&saml2");
+ } else if (protocol != null) {
+ builder.append("&protocol=").append(URLEncoder.encode(protocol, StandardCharsets.UTF_8));
}
return builder;
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/admin/resolvertest-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/admin/resolvertest-beans.xml
index 5bd5fdfa7..2a8b3aa54 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/admin/resolvertest-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/admin/resolvertest-beans.xml
@@ -129,9 +129,12 @@
<bean id="InitializeOutboundMessageContext"
class="net.shibboleth.idp.saml.profile.impl.InitializeOutboundMessageContext" scope="prototype" />
+ <bean id="ResolverTestUnfilteredPredicate" class="net.shibboleth.idp.profile.impl.ResolverTestUnfilteredPredicate" />
+
<bean id="AddSAML1AttributeStatementToAssertion"
class="net.shibboleth.idp.saml.saml1.profile.impl.AddAttributeStatementToAssertion" scope="prototype"
- p:transcoderRegistry-ref="shibboleth.AttributeRegistryService">
+ p:transcoderRegistry-ref="shibboleth.AttributeRegistryService"
+ p:useUnfilteredAttributesPredicate-ref="ResolverTestUnfilteredPredicate">
<property name="identifierGeneratorLookupStrategy">
<bean class="net.shibboleth.profile.config.navigate.IdentifierGenerationStrategyLookupFunction"
p:defaultIdentifierGenerationStrategy-ref="shibboleth.DefaultIdentifierGenerationStrategy" />
@@ -156,7 +159,8 @@
<bean id="AddSAML2AttributeStatementToAssertion"
class="net.shibboleth.idp.saml.saml2.profile.impl.AddAttributeStatementToAssertion" scope="prototype"
- p:transcoderRegistry-ref="shibboleth.AttributeRegistryService">
+ p:transcoderRegistry-ref="shibboleth.AttributeRegistryService"
+ p:useUnfilteredAttributesPredicate-ref="ResolverTestUnfilteredPredicate">
<property name="identifierGeneratorLookupStrategy">
<bean class="net.shibboleth.profile.config.navigate.IdentifierGenerationStrategyLookupFunction"
p:defaultIdentifierGenerationStrategy-ref="shibboleth.DefaultIdentifierGenerationStrategy" />
diff --git a/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/impl/ResolverTestUnfilteredPredicate.java b/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/impl/ResolverTestUnfilteredPredicate.java
new file mode 100644
index 000000000..8e88fb162
--- /dev/null
+++ b/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/impl/ResolverTestUnfilteredPredicate.java
@@ -0,0 +1,46 @@
+/*
+ * 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.idp.profile.impl;
+
+import java.util.function.Predicate;
+
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.profile.context.ProfileRequestContext;
+
+
+/**
+ * Condition that returns the result of evaluating {@link ResolverTestRequest#getUnfiltered()}.
+ *
+ * <p>The condition evaluates false in any scenarios in which the relevant message does not
+ * exist.</p>
+ *
+ * @since 5.2.2
+ */
+public class ResolverTestUnfilteredPredicate implements Predicate<ProfileRequestContext> {
+
+ /** {@inheritDoc} */
+ public boolean test(@Nullable final ProfileRequestContext input) {
+
+ final MessageContext mc = input != null ? input.getInboundMessageContext() : null;
+ if (mc != null && mc.getMessage() instanceof ResolverTestRequest req) {
+ return req.getUnfiltered();
+ }
+
+ return false;
+ }
+
+}
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseAddAttributeStatementToAssertion.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseAddAttributeStatementToAssertion.java
index 35a94fc03..925f5bd6f 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseAddAttributeStatementToAssertion.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/profile/impl/BaseAddAttributeStatementToAssertion.java
@@ -16,6 +16,7 @@ package net.shibboleth.idp.saml.profile.impl;
import java.util.Collection;
import java.util.function.Function;
+import java.util.function.Predicate;
import javax.annotation.Nonnull;
@@ -43,6 +44,7 @@ import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
import net.shibboleth.shared.annotation.constraint.NotEmpty;
import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.logic.PredicateSupport;
import net.shibboleth.shared.primitive.LoggerFactory;
import net.shibboleth.shared.security.IdentifierGenerationStrategy;
import net.shibboleth.shared.service.ReloadableService;
@@ -74,6 +76,9 @@ public abstract class BaseAddAttributeStatementToAssertion<T extends SAMLObject>
* result in an {@link net.shibboleth.idp.profile.IdPEventIds#UNABLE_ENCODE_ATTRIBUTE} transition.
*/
private boolean ignoringUnencodableAttributes;
+
+ /** Whether to use the unfiltered set of attributes. */
+ @Nonnull private Predicate<ProfileRequestContext> useUnfilteredAttributesPredicate;
/** Strategy used to locate the {@link IdentifierGenerationStrategy} to use. */
@NonnullAfterInit private Function<ProfileRequestContext,IdentifierGenerationStrategy> idGeneratorLookupStrategy;
@@ -102,6 +107,7 @@ public abstract class BaseAddAttributeStatementToAssertion<T extends SAMLObject>
public BaseAddAttributeStatementToAssertion() {
statementInOwnAssertion = false;
ignoringUnencodableAttributes = true;
+ useUnfilteredAttributesPredicate = PredicateSupport.alwaysFalse();
final Function<ProfileRequestContext,AttributeContext> acls =
new ChildContextLookup<>(AttributeContext.class).compose(
new ChildContextLookup<>(RelyingPartyContext.class));
@@ -158,6 +164,19 @@ public abstract class BaseAddAttributeStatementToAssertion<T extends SAMLObject>
checkSetterPreconditions();
ignoringUnencodableAttributes = flag;
}
+
+ /**
+ * Set condition for whether to encode the unfiltered attribute set instead of the filtered set.
+ *
+ * <p>Defaults to false, used only in specialized cases, not the main SAML profiles.</p>
+ *
+ * @param condition condition to set
+ */
+ public void setUseUnfilteredAttributesPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
+ checkSetterPreconditions();
+ useUnfilteredAttributesPredicate =
+ Constraint.isNotNull(condition, "Unfiltered attributes condition cannot be null");
+ }
/**
* Set the strategy used to locate the {@link AttributeContext} associated with a given
@@ -215,13 +234,18 @@ public abstract class BaseAddAttributeStatementToAssertion<T extends SAMLObject>
}
/**
- * Get the {@link AttributeContext} to encode.
+ * Get the collection to encode.
+ *
+ * @param profileRequestContext profile request context
*
- * @return the context to encode
+ * @return the collection to encode
*/
- @Nonnull public AttributeContext getAttributeContext() {
+ @Nonnull public Collection<IdPAttribute> getAttributesToEncode(
+ @Nonnull final ProfileRequestContext profileRequestContext) {
assert isPreExecuteCalled();
- return Constraint.isNotNull(attributeCtx, "AttributeContext has not been initialized yet");
+ Constraint.isNotNull(attributeCtx, "AttributeContext has not been initialized yet");
+ return useUnfilteredAttributesPredicate.test(profileRequestContext) ?
+ attributeCtx.getUnfilteredIdPAttributes().values() : attributeCtx.getIdPAttributes().values();
}
/**
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertion.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertion.java
index d102745ae..b3b632394 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertion.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/impl/AddAttributeStatementToAssertion.java
@@ -90,7 +90,7 @@ public class AddAttributeStatementToAssertion extends BaseAddAttributeStatementT
@Override protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
try {
final AttributeStatement statement = buildAttributeStatement(profileRequestContext,
- getAttributeContext().getIdPAttributes().values());
+ getAttributesToEncode(profileRequestContext));
if (statement == null) {
log.debug("{} No AttributeStatement was built, nothing to do", getLogPrefix());
return;
@@ -226,7 +226,7 @@ public class AddAttributeStatementToAssertion extends BaseAddAttributeStatementT
* an existing or new assertion in the response is returned, depending on the action setting. If the
* outbound message is anything else, null is returned.</p>
*/
- private class AssertionStrategy implements Function<ProfileRequestContext,Assertion> {
+ private final class AssertionStrategy implements Function<ProfileRequestContext,Assertion> {
/** {@inheritDoc} */
@Nullable public Assertion apply(@Nullable final ProfileRequestContext input) {
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertion.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertion.java
index fdef694dd..d1ba0c804 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertion.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/impl/AddAttributeStatementToAssertion.java
@@ -93,7 +93,7 @@ public class AddAttributeStatementToAssertion extends BaseAddAttributeStatementT
@Override protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
try {
final AttributeStatement statement = buildAttributeStatement(profileRequestContext,
- getAttributeContext().getIdPAttributes().values());
+ getAttributesToEncode(profileRequestContext));
if (statement == null) {
log.debug("{} No AttributeStatement was built, nothing to do", getLogPrefix());
return;
@@ -241,7 +241,7 @@ public class AddAttributeStatementToAssertion extends BaseAddAttributeStatementT
* an existing or new assertion in the response is returned, depending on the action setting. If the
* outbound message is anything else, null is returned.</p>
*/
- private class AssertionStrategy implements Function<ProfileRequestContext,Assertion> {
+ private final class AssertionStrategy implements Function<ProfileRequestContext,Assertion> {
/** {@inheritDoc} */
@Nullable public Assertion apply(@Nullable final ProfileRequestContext input) {
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list