[java-identity-provider] branch main updated: JSPROF-11 - Add attributes to resolve to resolving profile interface

Scott Cantor cantor.2 at osu.edu
Wed Sep 17 19:55:30 UTC 2025


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=816c2783978d5a231e3b02f1f1a7ec0a95e884b9

The following commit(s) were added to refs/heads/main by this push:
     new 816c27839 JSPROF-11 - Add attributes to resolve to resolving profile interface
816c27839 is described below

commit 816c2783978d5a231e3b02f1f1a7ec0a95e884b9
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Sep 17 15:55:26 2025 -0400

    JSPROF-11 - Add attributes to resolve to resolving profile interface
    
    https://shibboleth.atlassian.net/browse/JSPROF-11
    
    Implemented setting for all relevant profiles.
    Added to MDDriven wiring.
    Added to ResolveAttributes action.
---
 .../admin/BasicAdministrativeFlowDescriptor.java   | 44 +++++++++++++++++++
 .../cas/config/AbstractProtocolConfiguration.java  | 49 ++++++++++++++++++++++
 .../shibboleth/idp/conf/relying-party-mddriven.xml | 15 +++++++
 .../idp/profile/impl/ResolveAttributes.java        | 45 ++++++++++++++++++--
 .../impl/AttributeQueryProfileConfiguration.java   | 49 ++++++++++++++++++++++
 .../impl/BrowserSSOProfileConfiguration.java       | 44 +++++++++++++++++++
 .../impl/AttributeQueryProfileConfiguration.java   | 49 ++++++++++++++++++++++
 .../impl/BrowserSSOProfileConfiguration.java       | 44 +++++++++++++++++++
 8 files changed, 336 insertions(+), 3 deletions(-)

diff --git a/idp-admin-api/src/main/java/net/shibboleth/idp/admin/BasicAdministrativeFlowDescriptor.java b/idp-admin-api/src/main/java/net/shibboleth/idp/admin/BasicAdministrativeFlowDescriptor.java
index 401e5ffba..76db23878 100644
--- a/idp-admin-api/src/main/java/net/shibboleth/idp/admin/BasicAdministrativeFlowDescriptor.java
+++ b/idp-admin-api/src/main/java/net/shibboleth/idp/admin/BasicAdministrativeFlowDescriptor.java
@@ -38,6 +38,7 @@ import org.opensaml.security.config.SecurityConfiguration;
 
 import com.google.common.base.MoreObjects;
 
+import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.authn.principal.PrincipalServiceManager;
 import net.shibboleth.idp.profile.config.AbstractInterceptorAwareProfileConfiguration;
 import net.shibboleth.profile.config.OverriddenIssuerProfileConfiguration;
@@ -88,6 +89,9 @@ public class BasicAdministrativeFlowDescriptor extends AbstractInterceptorAwareP
 
     /** Whether attributes should be resolved in the course of the flow. */
     @Nonnull private Predicate<ProfileRequestContext> resolveAttributesPredicate;
+
+    /** Lookup strategy for requested IdP attribute names to pass into resolver. */
+    @Nonnull private Function<ProfileRequestContext,Collection<String>> requestedIdPAttributeNamesLookupStrategy;
     
     /** Lookup strategy for attribute recipient group ID. */
     @Nonnull private Function<ProfileRequestContext,String> attributeRecipientGroupIDLookupStrategy;
@@ -136,6 +140,7 @@ public class BasicAdministrativeFlowDescriptor extends AbstractInterceptorAwareP
         forceAuthnPredicate = PredicateSupport.alwaysFalse();
 
         resolveAttributesPredicate = PredicateSupport.alwaysFalse();
+        requestedIdPAttributeNamesLookupStrategy = FunctionSupport.constant(null);
         attributeRecipientGroupIDLookupStrategy = FunctionSupport.constant(null);
         
         builderFactory = XMLObjectProviderRegistrySupport.getBuilderFactory();
@@ -391,6 +396,45 @@ public class BasicAdministrativeFlowDescriptor extends AbstractInterceptorAwareP
         resolveAttributesPredicate = Constraint.isNotNull(condition, "Resolve attributes predicate cannot be null");
     }
     
+    /** {@inheritDoc} */
+    @Nonnull @Unmodifiable @NotLive public Collection<String> getRequestedIdPAttributeNames(
+            @Nullable final ProfileRequestContext profileRequestContext) {
+        final Collection<String> names = requestedIdPAttributeNamesLookupStrategy.apply(profileRequestContext);
+        if (names != null) {
+            return CollectionSupport.copyToSet(names);
+        }
+        return CollectionSupport.emptySet();
+    }
+    
+    /**
+     * Set {@link IdPAttribute} names to resolve (if resolving attributes). 
+     * 
+     * @param names {@link IdPAttribute} names to resolve
+     * 
+     * @since 5.2.0
+     */
+    public void setRequestedIdPAttributeNames(@Nullable final Collection<String> names) {
+        if (names == null || names.isEmpty()) {
+            requestedIdPAttributeNamesLookupStrategy = FunctionSupport.constant(null);
+        } else {
+            requestedIdPAttributeNamesLookupStrategy = FunctionSupport.constant(
+                    CollectionSupport.copyToSet(StringSupport.normalizeStringCollection(names)));
+        }
+    }
+    
+    /**
+     * Lookup strategy for {@link IdPAttribute} names to resolve (if resolving attributes).
+     * 
+     * @param strategy lookup strategy
+     * 
+     * @since 5.2.0
+     */
+    public void setRequestedIdPAttributeNamesLookupStrategy(
+            @Nonnull final Function<ProfileRequestContext,Collection<String>> strategy) {
+        requestedIdPAttributeNamesLookupStrategy =
+                Constraint.isNotNull(strategy, "Requested IdPAttribute names lookup strategy cannot be null");
+    }
+    
     /** {@inheritDoc} */
     @Nullable public String getAttributeRecipientGroupID(@Nullable final ProfileRequestContext profileRequestContext) {
         return attributeRecipientGroupIDLookupStrategy.apply(profileRequestContext);
diff --git a/idp-cas-api/src/main/java/net/shibboleth/idp/cas/config/AbstractProtocolConfiguration.java b/idp-cas-api/src/main/java/net/shibboleth/idp/cas/config/AbstractProtocolConfiguration.java
index 5f05aebef..a7e2d0791 100644
--- a/idp-cas-api/src/main/java/net/shibboleth/idp/cas/config/AbstractProtocolConfiguration.java
+++ b/idp-cas-api/src/main/java/net/shibboleth/idp/cas/config/AbstractProtocolConfiguration.java
@@ -15,6 +15,7 @@
 package net.shibboleth.idp.cas.config;
 
 import java.time.Duration;
+import java.util.Collection;
 import java.util.function.Function;
 import java.util.function.Predicate;
 
@@ -25,15 +26,20 @@ import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.security.config.BasicSecurityConfiguration;
 import org.opensaml.security.config.SecurityConfiguration;
 
+import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.cas.ticket.TicketIdentifierGenerationStrategy;
 import net.shibboleth.idp.profile.config.AbstractInterceptorAwareProfileConfiguration;
 import net.shibboleth.profile.config.AttributeResolvingProfileConfiguration;
 import net.shibboleth.shared.annotation.ConfigurationSetting;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.annotation.constraint.NotLive;
+import net.shibboleth.shared.annotation.constraint.Unmodifiable;
+import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.component.InitializableComponent;
 import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.logic.FunctionSupport;
 import net.shibboleth.shared.logic.PredicateSupport;
+import net.shibboleth.shared.primitive.StringSupport;
 
 /**
  * Base class for CAS protocol configuration.
@@ -59,6 +65,9 @@ public abstract class AbstractProtocolConfiguration extends AbstractInterceptorA
     /** Whether attributes should be resolved in the course of the profile. */
     @Nonnull private Predicate<ProfileRequestContext> resolveAttributesPredicate;
     
+    /** Lookup strategy for requested IdP attribute names to pass into resolver. */
+    @Nonnull private Function<ProfileRequestContext,Collection<String>> requestedIdPAttributeNamesLookupStrategy;
+    
     /** Lookup strategy for attribute recipient group ID. */
     @Nonnull private Function<ProfileRequestContext,String> attributeRecipientGroupIDLookupStrategy;
     
@@ -74,6 +83,7 @@ public abstract class AbstractProtocolConfiguration extends AbstractInterceptorA
         super(profileId);
         
         resolveAttributesPredicate = PredicateSupport.alwaysTrue();
+        requestedIdPAttributeNamesLookupStrategy = FunctionSupport.constant(null);
         attributeRecipientGroupIDLookupStrategy = FunctionSupport.constant(null);
         
         ticketValidityPeriodLookupStrategy = FunctionSupport.constant(DEFAULT_TICKET_VALIDITY_PERIOD);
@@ -156,6 +166,45 @@ public abstract class AbstractProtocolConfiguration extends AbstractInterceptorA
         resolveAttributesPredicate = Constraint.isNotNull(condition, "Resolve attributes predicate cannot be null");
     }
     
+    /** {@inheritDoc} */
+    @Nonnull @Unmodifiable @NotLive public Collection<String> getRequestedIdPAttributeNames(
+            @Nullable final ProfileRequestContext profileRequestContext) {
+        final Collection<String> names = requestedIdPAttributeNamesLookupStrategy.apply(profileRequestContext);
+        if (names != null) {
+            return CollectionSupport.copyToSet(names);
+        }
+        return CollectionSupport.emptySet();
+    }
+    
+    /**
+     * Set {@link IdPAttribute} names to resolve (if resolving attributes). 
+     * 
+     * @param names {@link IdPAttribute} names to resolve
+     * 
+     * @since 5.2.0
+     */
+    public void setRequestedIdPAttributeNames(@Nullable final Collection<String> names) {
+        if (names == null || names.isEmpty()) {
+            requestedIdPAttributeNamesLookupStrategy = FunctionSupport.constant(null);
+        } else {
+            requestedIdPAttributeNamesLookupStrategy = FunctionSupport.constant(
+                    CollectionSupport.copyToSet(StringSupport.normalizeStringCollection(names)));
+        }
+    }
+    
+    /**
+     * Lookup strategy for {@link IdPAttribute} names to resolve (if resolving attributes).
+     * 
+     * @param strategy lookup strategy
+     * 
+     * @since 5.2.0
+     */
+    public void setRequestedIdPAttributeNamesLookupStrategy(
+            @Nonnull final Function<ProfileRequestContext,Collection<String>> strategy) {
+        requestedIdPAttributeNamesLookupStrategy =
+                Constraint.isNotNull(strategy, "Requested IdPAttribute names lookup strategy cannot be null");
+    }
+    
     /** {@inheritDoc} */
     @Nullable public String getAttributeRecipientGroupID(@Nullable final ProfileRequestContext profileRequestContext) {
         return attributeRecipientGroupIDLookupStrategy.apply(profileRequestContext);
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 bca776910..fb4fcfb5f 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
@@ -260,6 +260,9 @@
                 <constructor-arg value="true" />
             </bean>
         </property>
+        <property name="requestedIdPAttributeNamesLookupStrategy">
+            <bean parent="shibboleth.MDDrivenSetProperty" p:propertyName="requestedIdPAttributeNames" />
+        </property>        
         <property name="attributeRecipientGroupIDLookupStrategy">
             <bean parent="shibboleth.MDDrivenStringProperty" p:propertyName="attributeRecipientGroupID" />
         </property>
@@ -298,6 +301,9 @@
                 <constructor-arg value="true" />
             </bean>
         </property>
+        <property name="requestedIdPAttributeNamesLookupStrategy">
+            <bean parent="shibboleth.MDDrivenSetProperty" p:propertyName="requestedIdPAttributeNames" />
+        </property>        
         <property name="attributeRecipientGroupIDLookupStrategy">
             <bean parent="shibboleth.MDDrivenStringProperty" p:propertyName="attributeRecipientGroupID" />
         </property>
@@ -344,6 +350,9 @@
                 </constructor-arg>
             </bean>
         </property>
+        <property name="requestedIdPAttributeNamesLookupStrategy">
+            <bean parent="shibboleth.MDDrivenSetProperty" p:propertyName="requestedIdPAttributeNames" />
+        </property>        
         <property name="attributeRecipientGroupIDLookupStrategy">
             <bean parent="shibboleth.MDDrivenStringProperty" p:propertyName="attributeRecipientGroupID" />
         </property>
@@ -426,6 +435,9 @@
                 <constructor-arg value="true" />
             </bean>
         </property>
+        <property name="requestedIdPAttributeNamesLookupStrategy">
+            <bean parent="shibboleth.MDDrivenSetProperty" p:propertyName="requestedIdPAttributeNames" />
+        </property>        
         <property name="attributeRecipientGroupIDLookupStrategy">
             <bean parent="shibboleth.MDDrivenStringProperty" p:propertyName="attributeRecipientGroupID" />
         </property>
@@ -706,6 +718,9 @@
                 <constructor-arg value="false" />
             </bean>
         </property>
+        <property name="requestedIdPAttributeNamesLookupStrategy">
+            <bean parent="shibboleth.MDDrivenSetProperty" p:propertyName="requestedIdPAttributeNames" />
+        </property>        
         <property name="attributeRecipientGroupIDLookupStrategy">
             <bean parent="shibboleth.MDDrivenStringProperty" p:propertyName="attributeRecipientGroupID" />
         </property>
diff --git a/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/impl/ResolveAttributes.java b/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/impl/ResolveAttributes.java
index 19b6f752a..c919077f8 100644
--- a/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/impl/ResolveAttributes.java
+++ b/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/impl/ResolveAttributes.java
@@ -61,7 +61,12 @@ public final class ResolveAttributes extends AbstractProfileAction {
 
     /** Class logger. */
     @Nonnull private final Logger log = LoggerFactory.getLogger(ResolveAttributes.class);
-
+    
+    /**
+     * Strategy used to locate the {@link RelyingPartyContext} associated with a given {@link ProfileRequestContext}.
+     */
+    @Nonnull private Function<ProfileRequestContext,RelyingPartyContext> relyingPartyContextLookupStrategy;
+    
     /** Service used to get the resolver used to fetch attributes. */
     @Nonnull private final ReloadableService<AttributeResolver> attributeResolverService;
 
@@ -91,6 +96,9 @@ public final class ResolveAttributes extends AbstractProfileAction {
     
     /** Whether to create and populate {@link AttributeResolutionContext}. */
     private boolean createResolutionContext;
+    
+    /** Tracked type-specific profile configuration. */ 
+    @Nullable private AttributeResolvingProfileConfiguration profileConfiguration;
 
     /**
      * Constructor.
@@ -99,6 +107,8 @@ public final class ResolveAttributes extends AbstractProfileAction {
      */
     @SuppressWarnings("null")
     public ResolveAttributes(@Nonnull final ReloadableService<AttributeResolver> resolverService) {
+        relyingPartyContextLookupStrategy = new ChildContextLookup<>(RelyingPartyContext.class);
+        
         attributeResolverService = Constraint.isNotNull(resolverService, "AttributeResolver cannot be null");
         
         issuerLookupStrategy = new IssuerLookupFunction();
@@ -118,6 +128,22 @@ public final class ResolveAttributes extends AbstractProfileAction {
         createResolutionContext = true;
     }
 
+    /**
+     * Set the strategy used to locate the {@link RelyingPartyContext} associated with a given
+     * {@link ProfileRequestContext}.
+     * 
+     * @param strategy strategy used to locate the {@link RelyingPartyContext} associated with a given
+     *         {@link ProfileRequestContext}
+     *         
+     * @since 5.2.0
+     */
+    public void setRelyingPartyContextLookupStrategy(
+            @Nonnull final Function<ProfileRequestContext,RelyingPartyContext> strategy) {
+        checkSetterPreconditions();
+        relyingPartyContextLookupStrategy = Constraint.isNotNull(strategy,
+                "RelyingPartyContext lookup strategy cannot be null");
+    }
+    
     /**
      * Set the strategy used to lookup the issuer for this attribute resolution.
      * 
@@ -247,6 +273,11 @@ public final class ResolveAttributes extends AbstractProfileAction {
             }
         }
         
+        final RelyingPartyContext ctx = relyingPartyContextLookupStrategy.apply(profileRequestContext);
+        if (ctx != null && ctx.getProfileConfig() instanceof AttributeResolvingProfileConfiguration pc) {
+            profileConfiguration = pc;
+        }
+        
         return true;
     }
 
@@ -294,6 +325,7 @@ public final class ResolveAttributes extends AbstractProfileAction {
         }
     }
 
+// Checkstyle: CyclomaticComplexity OFF
     /**
      * Fill in the resolution context data.
      * 
@@ -306,12 +338,18 @@ public final class ResolveAttributes extends AbstractProfileAction {
         resolutionContext.setResolutionLabel(resolutionLabel);
         
         // Populate requested attributes, if not already set.
+        // Otherwise reference the directly provided strategy and if that does nothing,
+        // fall back to profile config if available.
         if (resolutionContext.getRequestedIdPAttributeNames() == null
                 || resolutionContext.getRequestedIdPAttributeNames().isEmpty()) {
             assert attributesLookupStrategy != null;
             final Collection<String> names = attributesLookupStrategy.apply(profileRequestContext);
-            assert names != null;
-            resolutionContext.setRequestedIdPAttributeNames(names);
+            if (names != null && !names.isEmpty()) {
+                resolutionContext.setRequestedIdPAttributeNames(names);
+            } else if (profileConfiguration != null) {
+                resolutionContext.setRequestedIdPAttributeNames(
+                        profileConfiguration.getRequestedIdPAttributeNames(profileRequestContext));
+            }
         }
         
         if (null != principalNameLookupStrategy) {
@@ -345,5 +383,6 @@ public final class ResolveAttributes extends AbstractProfileAction {
             }
         }
     }
+// Checkstyle: CyclomaticComplexity ON
     
 }
\ No newline at end of file
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/config/impl/AttributeQueryProfileConfiguration.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/config/impl/AttributeQueryProfileConfiguration.java
index 0e2ed978f..1c89e0ace 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/config/impl/AttributeQueryProfileConfiguration.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/config/impl/AttributeQueryProfileConfiguration.java
@@ -14,6 +14,7 @@
 
 package net.shibboleth.idp.saml.saml1.profile.config.impl;
 
+import java.util.Collection;
 import java.util.function.Function;
 
 import javax.annotation.Nonnull;
@@ -22,10 +23,15 @@ import javax.annotation.Nullable;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.profile.logic.NoIntegrityMessageChannelPredicate;
 
+import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.saml.profile.config.SAMLAssertionProducingProfileConfiguration;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.annotation.constraint.NotLive;
+import net.shibboleth.shared.annotation.constraint.Unmodifiable;
+import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.logic.FunctionSupport;
+import net.shibboleth.shared.primitive.StringSupport;
 
 /** Configuration support for SAML 1 attribute query requests. */
 public class AttributeQueryProfileConfiguration extends AbstractSAML1AssertionProducingProfileConfiguration
@@ -34,6 +40,9 @@ public class AttributeQueryProfileConfiguration extends AbstractSAML1AssertionPr
     
     /** Name of profile counter. */
     @Nonnull @NotEmpty public static final String PROFILE_COUNTER = "net.shibboleth.idp.profiles.saml1.query.attribute";
+
+    /** Lookup strategy for requested IdP attribute names to pass into resolver. */
+    @Nonnull private Function<ProfileRequestContext,Collection<String>> requestedIdPAttributeNamesLookupStrategy;
     
     /** Lookup strategy for attribute recipient group ID. */
     @Nonnull private Function<ProfileRequestContext,String> attributeRecipientGroupIDLookupStrategy;
@@ -51,6 +60,7 @@ public class AttributeQueryProfileConfiguration extends AbstractSAML1AssertionPr
     protected AttributeQueryProfileConfiguration(@Nonnull @NotEmpty final String profileId) {
         super(profileId);
         setSignResponsesPredicate(new NoIntegrityMessageChannelPredicate());
+        requestedIdPAttributeNamesLookupStrategy = FunctionSupport.constant(null);
         attributeRecipientGroupIDLookupStrategy = FunctionSupport.constant(null);
     }
 
@@ -59,6 +69,45 @@ public class AttributeQueryProfileConfiguration extends AbstractSAML1AssertionPr
         return true;
     }
 
+    /** {@inheritDoc} */
+    @Nonnull @Unmodifiable @NotLive public Collection<String> getRequestedIdPAttributeNames(
+            @Nullable final ProfileRequestContext profileRequestContext) {
+        final Collection<String> names = requestedIdPAttributeNamesLookupStrategy.apply(profileRequestContext);
+        if (names != null) {
+            return CollectionSupport.copyToSet(names);
+        }
+        return CollectionSupport.emptySet();
+    }
+    
+    /**
+     * Set {@link IdPAttribute} names to resolve (if resolving attributes). 
+     * 
+     * @param names {@link IdPAttribute} names to resolve
+     * 
+     * @since 5.2.0
+     */
+    public void setRequestedIdPAttributeNames(@Nullable final Collection<String> names) {
+        if (names == null || names.isEmpty()) {
+            requestedIdPAttributeNamesLookupStrategy = FunctionSupport.constant(null);
+        } else {
+            requestedIdPAttributeNamesLookupStrategy = FunctionSupport.constant(
+                    CollectionSupport.copyToSet(StringSupport.normalizeStringCollection(names)));
+        }
+    }
+    
+    /**
+     * Lookup strategy for {@link IdPAttribute} names to resolve (if resolving attributes).
+     * 
+     * @param strategy lookup strategy
+     * 
+     * @since 5.2.0
+     */
+    public void setRequestedIdPAttributeNamesLookupStrategy(
+            @Nonnull final Function<ProfileRequestContext,Collection<String>> strategy) {
+        requestedIdPAttributeNamesLookupStrategy =
+                Constraint.isNotNull(strategy, "Requested IdPAttribute names lookup strategy cannot be null");
+    }
+    
     /** {@inheritDoc} */
     @Nullable public String getAttributeRecipientGroupID(@Nullable final ProfileRequestContext profileRequestContext) {
         return attributeRecipientGroupIDLookupStrategy.apply(profileRequestContext);
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/config/impl/BrowserSSOProfileConfiguration.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/config/impl/BrowserSSOProfileConfiguration.java
index bc7628b91..4e0363ea1 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/config/impl/BrowserSSOProfileConfiguration.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml1/profile/config/impl/BrowserSSOProfileConfiguration.java
@@ -26,6 +26,7 @@ import javax.annotation.Nullable;
 
 import org.opensaml.profile.context.ProfileRequestContext;
 
+import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.authn.config.AuthenticationProfileConfiguration;
 import net.shibboleth.shared.annotation.constraint.NonNegative;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
@@ -49,6 +50,9 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML1AssertionProduc
     /** Whether attributes should be resolved in the course of the profile. */
     @Nonnull private Predicate<ProfileRequestContext> resolveAttributesPredicate;
 
+    /** Lookup strategy for requested IdP attribute names to pass into resolver. */
+    @Nonnull private Function<ProfileRequestContext,Collection<String>> requestedIdPAttributeNamesLookupStrategy;
+    
     /** Lookup strategy for attribute recipient group ID. */
     @Nonnull private Function<ProfileRequestContext,String> attributeRecipientGroupIDLookupStrategy;
     
@@ -88,6 +92,7 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML1AssertionProduc
         super(profileId);
         setSignResponses(true);
         resolveAttributesPredicate = PredicateSupport.alwaysTrue();
+        requestedIdPAttributeNamesLookupStrategy = FunctionSupport.constant(null);
         attributeRecipientGroupIDLookupStrategy = FunctionSupport.constant(null);
         includeAttributeStatementPredicate = PredicateSupport.alwaysFalse();
         authenticationFlowsLookupStrategy = FunctionSupport.constant(null);
@@ -121,6 +126,45 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML1AssertionProduc
         resolveAttributesPredicate = Constraint.isNotNull(condition, "Resolve attributes predicate cannot be null");
     }
 
+    /** {@inheritDoc} */
+    @Nonnull @Unmodifiable @NotLive public Collection<String> getRequestedIdPAttributeNames(
+            @Nullable final ProfileRequestContext profileRequestContext) {
+        final Collection<String> names = requestedIdPAttributeNamesLookupStrategy.apply(profileRequestContext);
+        if (names != null) {
+            return CollectionSupport.copyToSet(names);
+        }
+        return CollectionSupport.emptySet();
+    }
+    
+    /**
+     * Set {@link IdPAttribute} names to resolve (if resolving attributes). 
+     * 
+     * @param names {@link IdPAttribute} names to resolve
+     * 
+     * @since 5.2.0
+     */
+    public void setRequestedIdPAttributeNames(@Nullable final Collection<String> names) {
+        if (names == null || names.isEmpty()) {
+            requestedIdPAttributeNamesLookupStrategy = FunctionSupport.constant(null);
+        } else {
+            requestedIdPAttributeNamesLookupStrategy = FunctionSupport.constant(
+                    CollectionSupport.copyToSet(StringSupport.normalizeStringCollection(names)));
+        }
+    }
+    
+    /**
+     * Lookup strategy for {@link IdPAttribute} names to resolve (if resolving attributes).
+     * 
+     * @param strategy lookup strategy
+     * 
+     * @since 5.2.0
+     */
+    public void setRequestedIdPAttributeNamesLookupStrategy(
+            @Nonnull final Function<ProfileRequestContext,Collection<String>> strategy) {
+        requestedIdPAttributeNamesLookupStrategy =
+                Constraint.isNotNull(strategy, "Requested IdPAttribute names lookup strategy cannot be null");
+    }
+    
     /** {@inheritDoc} */
     @Nullable public String getAttributeRecipientGroupID(@Nullable final ProfileRequestContext profileRequestContext) {
         return attributeRecipientGroupIDLookupStrategy.apply(profileRequestContext);
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/impl/AttributeQueryProfileConfiguration.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/impl/AttributeQueryProfileConfiguration.java
index ab9687ccf..a2204d320 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/impl/AttributeQueryProfileConfiguration.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/impl/AttributeQueryProfileConfiguration.java
@@ -14,6 +14,7 @@
 
 package net.shibboleth.idp.saml.saml2.profile.config.impl;
 
+import java.util.Collection;
 import java.util.function.Function;
 import java.util.function.Predicate;
 
@@ -25,10 +26,15 @@ import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.profile.logic.NoConfidentialityMessageChannelPredicate;
 import org.opensaml.profile.logic.NoIntegrityMessageChannelPredicate;
 
+import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.annotation.constraint.NotLive;
+import net.shibboleth.shared.annotation.constraint.Unmodifiable;
+import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.logic.FunctionSupport;
 import net.shibboleth.shared.logic.PredicateSupport;
+import net.shibboleth.shared.primitive.StringSupport;
 
 /** Configuration support for IdP SAML 2.0 attribute query profile. */
 public class AttributeQueryProfileConfiguration extends AbstractSAML2AssertionProducingProfileConfiguration
@@ -40,6 +46,9 @@ public class AttributeQueryProfileConfiguration extends AbstractSAML2AssertionPr
     /** Whether the FriendlyName attribute should be randomized when encoding Attributes. */
     @Nonnull private Predicate<ProfileRequestContext> randomizeFriendlyNamePredicate;
 
+    /** Lookup strategy for requested IdP attribute names to pass into resolver. */
+    @Nonnull private Function<ProfileRequestContext,Collection<String>> requestedIdPAttributeNamesLookupStrategy;
+    
     /** Lookup strategy for attribute recipient group ID. */
     @Nonnull private Function<ProfileRequestContext,String> attributeRecipientGroupIDLookupStrategy;
     
@@ -64,6 +73,7 @@ public class AttributeQueryProfileConfiguration extends AbstractSAML2AssertionPr
         setSignResponsesPredicate(new NoIntegrityMessageChannelPredicate());
         setEncryptAssertionsPredicate(new NoConfidentialityMessageChannelPredicate());
         randomizeFriendlyNamePredicate = PredicateSupport.alwaysFalse();
+        requestedIdPAttributeNamesLookupStrategy = FunctionSupport.constant(null);
         attributeRecipientGroupIDLookupStrategy = FunctionSupport.constant(null);
         
         signSOAPRequestsPredicate = new org.opensaml.messaging.logic.NoIntegrityMessageChannelPredicate();
@@ -107,6 +117,45 @@ public class AttributeQueryProfileConfiguration extends AbstractSAML2AssertionPr
         return true;
     }
 
+    /** {@inheritDoc} */
+    @Nonnull @Unmodifiable @NotLive public Collection<String> getRequestedIdPAttributeNames(
+            @Nullable final ProfileRequestContext profileRequestContext) {
+        final Collection<String> names = requestedIdPAttributeNamesLookupStrategy.apply(profileRequestContext);
+        if (names != null) {
+            return CollectionSupport.copyToSet(names);
+        }
+        return CollectionSupport.emptySet();
+    }
+    
+    /**
+     * Set {@link IdPAttribute} names to resolve (if resolving attributes). 
+     * 
+     * @param names {@link IdPAttribute} names to resolve
+     * 
+     * @since 5.2.0
+     */
+    public void setRequestedIdPAttributeNames(@Nullable final Collection<String> names) {
+        if (names == null || names.isEmpty()) {
+            requestedIdPAttributeNamesLookupStrategy = FunctionSupport.constant(null);
+        } else {
+            requestedIdPAttributeNamesLookupStrategy = FunctionSupport.constant(
+                    CollectionSupport.copyToSet(StringSupport.normalizeStringCollection(names)));
+        }
+    }
+    
+    /**
+     * Lookup strategy for {@link IdPAttribute} names to resolve (if resolving attributes).
+     * 
+     * @param strategy lookup strategy
+     * 
+     * @since 5.2.0
+     */
+    public void setRequestedIdPAttributeNamesLookupStrategy(
+            @Nonnull final Function<ProfileRequestContext,Collection<String>> strategy) {
+        requestedIdPAttributeNamesLookupStrategy =
+                Constraint.isNotNull(strategy, "Requested IdPAttribute names lookup strategy cannot be null");
+    }
+    
     /** {@inheritDoc} */
     @Nullable public String getAttributeRecipientGroupID(@Nullable final ProfileRequestContext profileRequestContext) {
         return attributeRecipientGroupIDLookupStrategy.apply(profileRequestContext);
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/impl/BrowserSSOProfileConfiguration.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/impl/BrowserSSOProfileConfiguration.java
index 699ba5cea..5137eefd0 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/impl/BrowserSSOProfileConfiguration.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/saml2/profile/config/impl/BrowserSSOProfileConfiguration.java
@@ -25,6 +25,7 @@ import java.util.function.Predicate;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import net.shibboleth.idp.attribute.IdPAttribute;
 import net.shibboleth.idp.authn.config.AuthenticationProfileConfiguration;
 import net.shibboleth.idp.saml.profile.config.logic.ProxyAwareForceAuthnPredicate;
 import net.shibboleth.idp.saml.saml2.profile.config.navigate.ProxyAwareAuthnContextComparisonLookupFunction;
@@ -59,6 +60,9 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML2AssertionProduc
     /** Whether attributes should be resolved in the course of the profile. */
     @Nonnull private Predicate<ProfileRequestContext> resolveAttributesPredicate;
 
+    /** Lookup strategy for requested IdP attribute names to pass into resolver. */
+    @Nonnull private Function<ProfileRequestContext,Collection<String>> requestedIdPAttributeNamesLookupStrategy;
+    
     /** Lookup strategy for attribute recipient group ID. */
     @Nonnull private Function<ProfileRequestContext,String> attributeRecipientGroupIDLookupStrategy;
     
@@ -165,6 +169,7 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML2AssertionProduc
         setSignResponses(true);
         setEncryptAssertions(true);
         resolveAttributesPredicate = PredicateSupport.alwaysTrue();
+        requestedIdPAttributeNamesLookupStrategy = FunctionSupport.constant(null);
         attributeRecipientGroupIDLookupStrategy = FunctionSupport.constant(null);
         includeAttributeStatementPredicate = PredicateSupport.alwaysTrue();
         ignoreScoping = PredicateSupport.alwaysFalse();
@@ -218,6 +223,45 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML2AssertionProduc
         resolveAttributesPredicate = Constraint.isNotNull(condition, "Resolve attributes predicate cannot be null");
     }
 
+    /** {@inheritDoc} */
+    @Nonnull @Unmodifiable @NotLive public Collection<String> getRequestedIdPAttributeNames(
+            @Nullable final ProfileRequestContext profileRequestContext) {
+        final Collection<String> names = requestedIdPAttributeNamesLookupStrategy.apply(profileRequestContext);
+        if (names != null) {
+            return CollectionSupport.copyToSet(names);
+        }
+        return CollectionSupport.emptySet();
+    }
+    
+    /**
+     * Set {@link IdPAttribute} names to resolve (if resolving attributes). 
+     * 
+     * @param names {@link IdPAttribute} names to resolve
+     * 
+     * @since 5.2.0
+     */
+    public void setRequestedIdPAttributeNames(@Nullable final Collection<String> names) {
+        if (names == null || names.isEmpty()) {
+            requestedIdPAttributeNamesLookupStrategy = FunctionSupport.constant(null);
+        } else {
+            requestedIdPAttributeNamesLookupStrategy = FunctionSupport.constant(
+                    CollectionSupport.copyToSet(StringSupport.normalizeStringCollection(names)));
+        }
+    }
+    
+    /**
+     * Lookup strategy for {@link IdPAttribute} names to resolve (if resolving attributes).
+     * 
+     * @param strategy lookup strategy
+     * 
+     * @since 5.2.0
+     */
+    public void setRequestedIdPAttributeNamesLookupStrategy(
+            @Nonnull final Function<ProfileRequestContext,Collection<String>> strategy) {
+        requestedIdPAttributeNamesLookupStrategy =
+                Constraint.isNotNull(strategy, "Requested IdPAttribute names lookup strategy cannot be null");
+    }
+    
     /** {@inheritDoc} */
     @Nullable public String getAttributeRecipientGroupID(@Nullable final ProfileRequestContext profileRequestContext) {
         return attributeRecipientGroupIDLookupStrategy.apply(profileRequestContext);

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


More information about the commits mailing list