[java-plugin-shibd] branch main updated: JSHIBD-24 - Application and RelyingPartyConfiguration inheritance
Codeberg
noreply at shibboleth.net
Mon Oct 12 21:46:49 UTC 2026
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch main
in repository java-plugin-shibd.
View the commit online:
https://codeberg.org/Shibboleth/java-plugin-shibd/commit/8e04d169bcabaaa726cceda6fb70c3dd538791b9
The following commit(s) were added to refs/heads/main by this push:
new 8e04d16 JSHIBD-24 - Application and RelyingPartyConfiguration inheritance
8e04d16 is described below
commit 8e04d169bcabaaa726cceda6fb70c3dd538791b9
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Mon Oct 12 17:46:32 2026 -0400
JSHIBD-24 - Application and RelyingPartyConfiguration inheritance
https://shibboleth.atlassian.net/browse/JSHIBD-24
Reimplement delegation of RelyingPartyConfigurations.
Use standard BasicRelyingPartyConfiguration objects wrapping at runtime.
---
.../net/shibboleth/sp/conf/agents-system.xml | 16 +-
.../net/shibboleth/sp/impl/BasicApplication.java | 32 ++--
.../impl/DelegatingRelyingPartyConfiguration.java | 103 ++++++++-----
.../sp/impl/RelyingPartyConfigurationSupport.java | 170 ---------------------
4 files changed, 89 insertions(+), 232 deletions(-)
diff --git a/sp-conf-impl/src/main/resources/net/shibboleth/sp/conf/agents-system.xml b/sp-conf-impl/src/main/resources/net/shibboleth/sp/conf/agents-system.xml
index 56c72ae..dd240c6 100644
--- a/sp-conf-impl/src/main/resources/net/shibboleth/sp/conf/agents-system.xml
+++ b/sp-conf-impl/src/main/resources/net/shibboleth/sp/conf/agents-system.xml
@@ -107,26 +107,24 @@
class="net.shibboleth.sp.security.config.impl.BasicHttpClientSecurityConfiguration"
c:resolver-ref="shibboleth.sp.CredentialResolverBridge" />
- <!-- We set the honor-empty flag on this so that the typical case of an empty profile map is assumed to be valid. -->
- <bean id="DefaultUnverifiedRelyingPartyConfiguration" class="net.shibboleth.sp.impl.DelegatingRelyingPartyConfiguration"
- p:honorEmptyProfileCollection="true"
+ <bean id="DefaultUnverifiedRelyingPartyConfiguration" class="net.shibboleth.profile.relyingparty.BasicRelyingPartyConfiguration"
p:profileConfigurations="#{getObject('shibboleth.sp.UnverifiedProfileConfigurations') ?: getObject('UnverifiedProfileConfigurations')}" />
<!-- Parent bean for arbitrary instances. -->
- <bean id="RelyingParty" abstract="true" class="net.shibboleth.sp.impl.DelegatingRelyingPartyConfiguration" />
+ <bean id="RelyingParty" abstract="true" class="net.shibboleth.profile.relyingparty.BasicRelyingPartyConfiguration" />
<!-- Parent bean for RelyingParty overrides based on activation by name(s). -->
<bean id="RelyingPartyByName" abstract="true"
- class="net.shibboleth.sp.impl.RelyingPartyConfigurationSupport" factory-method="byName" />
+ class="net.shibboleth.saml.relyingparty.RelyingPartyConfigurationSupport" factory-method="byName" />
<!-- Parent bean for RelyingParty overrides based on activation by group or SAML affiliation. -->
<bean id="RelyingPartyByGroup" abstract="true"
- class="net.shibboleth.sp.impl.RelyingPartyConfigurationSupport" factory-method="byGroup"
+ class="net.shibboleth.saml.relyingparty.RelyingPartyConfigurationSupport" factory-method="byGroup"
c:resolver-ref="shibboleth.MetadataResolver" />
<!-- Parent bean for RelyingParty overrides based on activation by local containment only. -->
<bean id="RelyingPartyByEntitiesDescriptor" abstract="true"
- class="net.shibboleth.sp.impl.RelyingPartyConfigurationSupport" factory-method="byGroup">
+ class="net.shibboleth.saml.relyingparty.RelyingPartyConfigurationSupport" factory-method="byGroup">
<constructor-arg name="resolver">
<null/>
</constructor-arg>
@@ -134,12 +132,12 @@
<!-- Parent bean for RelyingParty overrides based on activation by tag. -->
<bean id="RelyingPartyByTag" abstract="true"
- class="net.shibboleth.sp.impl.RelyingPartyConfigurationSupport" factory-method="byTag"
+ class="net.shibboleth.saml.relyingparty.RelyingPartyConfigurationSupport" factory-method="byTag"
c:trim="false" c:matchAll="false" />
<!-- Parent bean for RelyingParty overrides based on activation by tag. -->
<bean id="RelyingPartyByMappedTag" abstract="true"
- class="net.shibboleth.sp.impl.RelyingPartyConfigurationSupport" factory-method="byMappedTag"
+ class="net.shibboleth.saml.relyingparty.RelyingPartyConfigurationSupport" factory-method="byMappedTag"
c:trim="false" c:matchAll="false" />
<bean id="TagCandidate" abstract="true"
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/impl/BasicApplication.java b/sp-server-impl/src/main/java/net/shibboleth/sp/impl/BasicApplication.java
index 7bb58dd..32097bf 100644
--- a/sp-server-impl/src/main/java/net/shibboleth/sp/impl/BasicApplication.java
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/impl/BasicApplication.java
@@ -22,6 +22,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
+import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -943,13 +944,16 @@ public class BasicApplication extends BasicRelyingPartyConfiguration implements
checkSetterPreconditions();
if (configs != null) {
- configs.stream()
- .filter(DelegatingRelyingPartyConfiguration.class::isInstance)
- .map(DelegatingRelyingPartyConfiguration.class::cast)
- .forEach(rpc -> {rpc.setApplication(this);});
+ final Collection<DelegatingRelyingPartyConfiguration> wrapped =
+ configs.stream()
+ .map(rpc -> { return new DelegatingRelyingPartyConfiguration(this, rpc, false); })
+ .collect(CollectionSupport.nonnullCollector(Collectors.toUnmodifiableList())).get();
+
+ relyingPartyResolver.setRelyingPartyConfigurations(wrapped);
+ } else {
+ relyingPartyResolver.setRelyingPartyConfigurations(configs);
}
- relyingPartyResolver.setRelyingPartyConfigurations(configs);
}
/**
@@ -959,7 +963,12 @@ public class BasicApplication extends BasicRelyingPartyConfiguration implements
*/
public void setDefaultConfiguration(@Nullable final RelyingPartyConfiguration configuration) {
checkSetterPreconditions();
- relyingPartyResolver.setDefaultConfiguration(configuration);
+ if (configuration != null) {
+ relyingPartyResolver.setDefaultConfiguration(
+ new DelegatingRelyingPartyConfiguration(this, configuration, false));
+ } else {
+ relyingPartyResolver.setDefaultConfiguration(configuration);
+ }
}
/**
@@ -970,12 +979,13 @@ public class BasicApplication extends BasicRelyingPartyConfiguration implements
*/
public void setUnverifiedConfiguration(@Nullable final RelyingPartyConfiguration configuration) {
checkSetterPreconditions();
-
- if (configuration instanceof DelegatingRelyingPartyConfiguration del) {
- del.setApplication(this);
+
+ if (configuration != null) {
+ relyingPartyResolver.setUnverifiedConfiguration(
+ new DelegatingRelyingPartyConfiguration(this, configuration, true));
+ } else {
+ relyingPartyResolver.setUnverifiedConfiguration(configuration);
}
-
- relyingPartyResolver.setUnverifiedConfiguration(configuration);
}
/**
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/impl/DelegatingRelyingPartyConfiguration.java b/sp-server-impl/src/main/java/net/shibboleth/sp/impl/DelegatingRelyingPartyConfiguration.java
index af1d589..d8aaece 100644
--- a/sp-server-impl/src/main/java/net/shibboleth/sp/impl/DelegatingRelyingPartyConfiguration.java
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/impl/DelegatingRelyingPartyConfiguration.java
@@ -15,6 +15,7 @@
package net.shibboleth.sp.impl;
import java.util.Map;
+import java.util.function.Predicate;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -23,87 +24,105 @@ import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.security.config.SecurityConfiguration;
import net.shibboleth.profile.config.ProfileConfiguration;
-import net.shibboleth.profile.relyingparty.BasicRelyingPartyConfiguration;
+import net.shibboleth.profile.relyingparty.RelyingPartyConfiguration;
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.AbstractIdentifiableInitializableComponent;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.StringSupport;
import net.shibboleth.sp.Application;
/**
- * Subclass of {@link BasicRelyingPartyConfiguration} that will handle absent settings
+ * Wrapper for {@link RelyingPartyConfiguration} that will handle absent settings
* by delegating to an injected instance of {@link Application}.
*/
-public class DelegatingRelyingPartyConfiguration extends BasicRelyingPartyConfiguration {
+public class DelegatingRelyingPartyConfiguration extends AbstractIdentifiableInitializableComponent
+ implements RelyingPartyConfiguration, Predicate<ProfileRequestContext> {
- /** Delegation source. */
- @Nullable private Application application;
+ /** Inheritance source. */
+ @Nonnull private Application application;
+
+ /** Delegation target. */
+ @Nonnull private RelyingPartyConfiguration relyingPartyConfiguration;
/** Whether to treat an empty profile configuration set as a valid outcome. */
private boolean honorEmptyProfileCollection;
/**
- * Sets the {@link Application} to delegate to.
- *
- * @param app object to delegate to
+ * Constructor.
+ *
+ * @param app inheritance source
+ * @param config delegation target
+ * @param honorEmpty whether to treat empty profile configuration collection as legitimate
*/
- public void setApplication(@Nullable final Application app) {
- application = app;
+ public DelegatingRelyingPartyConfiguration(@Nonnull final Application app,
+ @Nonnull final RelyingPartyConfiguration config, final boolean honorEmpty) {
+ application = Constraint.isNotNull(app, "Application cannot be null");
+ relyingPartyConfiguration = Constraint.isNotNull(config, "RelyingPartyConfiguration cannot be null");
+ honorEmptyProfileCollection = honorEmpty;
}
-
- /**
- * Sets whether to treat an empty collection returned by {@link #getProfileConfigurations(ProfileRequestContext)}
- * as a valid outcome, thus not forwarding the lookup on to the injected {@link Application}.
- *
- * <p>Defaults to false, disallowing an empty collection as an expected result.</p>
- *
- * @param flag flag to set
- */
- public void setHonorEmptyProfileCollection(final boolean flag) {
- checkSetterPreconditions();
- honorEmptyProfileCollection = flag;
+
+ /** {@inheritDoc} */
+ @Override
+ @Nullable public String getId() {
+ return relyingPartyConfiguration.getId();
+ }
+
+ /** {@inheritDoc} */
+ public boolean test(@Nullable final ProfileRequestContext input) {
+ return relyingPartyConfiguration.test(input);
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("removal")
+ public void setResponderId(@Nullable final String issuer) {
+ relyingPartyConfiguration.setResponderId(issuer);
}
/** {@inheritDoc} */
- @Override
@Nullable public String getIssuer(@Nullable final ProfileRequestContext profileRequestContext) {
- final String issuer = super.getIssuer(profileRequestContext);
+ final String issuer = relyingPartyConfiguration.getIssuer(profileRequestContext);
if (issuer != null) {
return issuer;
- } else if (application != null) {
- return application.getIssuer(profileRequestContext);
- } else {
- return null;
}
+ return application.getIssuer(profileRequestContext);
}
/** {@inheritDoc} */
- @Override
@Nullable public SecurityConfiguration getSecurityConfiguration(
@Nullable final ProfileRequestContext profileRequestContext) {
- final SecurityConfiguration config = super.getSecurityConfiguration(profileRequestContext);
+ final SecurityConfiguration config = relyingPartyConfiguration.getSecurityConfiguration(profileRequestContext);
if (config != null) {
return config;
- } else if (application != null) {
- return application.getSecurityConfiguration(profileRequestContext);
- } else {
- return null;
}
+ return application.getSecurityConfiguration(profileRequestContext);
}
/** {@inheritDoc} */
- @Override
- @Nonnull @Unmodifiable @NotLive public Map<String, ProfileConfiguration> getProfileConfigurations(
+ @Nonnull @Unmodifiable @NotLive public Map<String,ProfileConfiguration> getProfileConfigurations(
@Nullable final ProfileRequestContext profileRequestContext) {
- final var profiles = super.getProfileConfigurations(profileRequestContext);
+ final var profiles = relyingPartyConfiguration.getProfileConfigurations(profileRequestContext);
if (honorEmptyProfileCollection || !profiles.isEmpty()) {
return profiles;
- } else if (application != null) {
- return application.getProfileConfigurations(profileRequestContext);
- } else {
- return CollectionSupport.emptyMap();
}
+ return application.getProfileConfigurations(profileRequestContext);
+ }
+
+ /** {@inheritDoc} */
+ public ProfileConfiguration getProfileConfiguration(ProfileRequestContext profileRequestContext, String profileId) {
+ final String trimmedId = StringSupport.trimOrNull(profileId);
+ if (trimmedId == null) {
+ return null;
+ }
+
+ return getProfileConfigurations(profileRequestContext).get(trimmedId);
+ }
+
+ /** {@inheritDoc} */
+ public boolean isDetailedErrors(ProfileRequestContext profileRequestContext) {
+ return relyingPartyConfiguration.isDetailedErrors(profileRequestContext);
}
}
\ No newline at end of file
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/impl/RelyingPartyConfigurationSupport.java b/sp-server-impl/src/main/java/net/shibboleth/sp/impl/RelyingPartyConfigurationSupport.java
deleted file mode 100644
index a3d26ea..0000000
--- a/sp-server-impl/src/main/java/net/shibboleth/sp/impl/RelyingPartyConfigurationSupport.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * 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.sp.impl;
-
-import java.util.Collection;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.saml.common.messaging.context.navigate.EntityDescriptorLookupFunction;
-import org.opensaml.saml.common.profile.logic.EntityAttributesPredicate;
-import org.opensaml.saml.common.profile.logic.EntityAttributesPredicate.Candidate;
-import org.opensaml.saml.common.profile.logic.EntityGroupNamePredicate;
-import org.opensaml.saml.metadata.resolver.MetadataResolver;
-import org.opensaml.saml.saml2.metadata.AffiliationDescriptor;
-import org.opensaml.saml.saml2.metadata.EntitiesDescriptor;
-import org.opensaml.saml.saml2.metadata.EntityDescriptor;
-
-import net.shibboleth.profile.relyingparty.RelyingPartyConfiguration;
-import net.shibboleth.profile.context.logic.RelyingPartyIdPredicate;
-import net.shibboleth.saml.profile.context.logic.MappedEntityAttributesPredicate;
-import net.shibboleth.saml.profile.context.navigate.SAMLMetadataContextLookupFunction;
-import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.logic.StrategyIndirectedPredicate;
-
-/**
- * This is a duplicate of a higher level class in order to override the "type" of the
- * {@link RelyingPartyConfiguration} to create.
- *
- * // TODO: adjust the original class to support overriding type creation somehow
- */
-public final class RelyingPartyConfigurationSupport {
-
- /** Constructor. */
- private RelyingPartyConfigurationSupport() {
-
- }
-
- /**
- * A shorthand method for constructing a {@link RelyingPartyConfiguration} with an activation condition
- * based on one or more relying party IDs.
- *
- * <p>If a single ID is supplied, then the ID is also set as the identifier for the configuration.</p>
- *
- * @param relyingPartyIds the relying parties for which the configuration should be active
- *
- * @return a default-constructed configuration with the appropriate condition set
- */
- @Nonnull public static RelyingPartyConfiguration byName(@Nonnull final Collection<String> relyingPartyIds) {
-
- Constraint.isNotNull(relyingPartyIds, "Relying Party ID list cannot be null");
-
- final DelegatingRelyingPartyConfiguration config = new DelegatingRelyingPartyConfiguration();
- config.setActivationCondition(new RelyingPartyIdPredicate(relyingPartyIds));
-
- final StringBuffer name = new StringBuffer("EntityNames[");
- for (final String rpId: relyingPartyIds) {
- name.append(rpId).append(',');
-
- }
- name.append(']');
- config.setId(name.toString());
- return config;
- }
-
- /**
- * A shorthand method for constructing a {@link RelyingPartyConfiguration} with an activation condition
- * based on one or more {@link EntitiesDescriptor} groups, and optionally via {@link AffiliationDescriptor} lookup.
- *
- * @param groupNames the group names
- * @param resolver optional metadata source for affiliation lookup
- *
- * @return a default-constructed configuration with the appropriate condition set
- */
- @Nonnull public static RelyingPartyConfiguration byGroup(@Nonnull final Collection<String> groupNames,
- @Nullable final MetadataResolver resolver) {
- Constraint.isNotNull(groupNames, "Group name list cannot be null");
-
- // We adapt an OpenSAML Predicate applying to an EntityDescriptor by indirecting the lookup of the
- // EntityDescriptor to a lookup sequence of PRC -> RPC -> SAMLMetadataContext -> EntityDescriptor.
-
- final StrategyIndirectedPredicate<ProfileRequestContext,EntityDescriptor> indirectPredicate =
- new StrategyIndirectedPredicate<>(
- new EntityDescriptorLookupFunction().compose(new SAMLMetadataContextLookupFunction()),
- new EntityGroupNamePredicate(groupNames, resolver));
-
- final DelegatingRelyingPartyConfiguration config = new DelegatingRelyingPartyConfiguration();
- config.setActivationCondition(indirectPredicate);
-
- final StringBuffer name = new StringBuffer("EntityGroups[");
- for (final String group: groupNames) {
- name.append(group).append(',');
-
- }
- name.append(']');
- config.setId(name.toString());
- return config;
- }
-
-
- /**
- * A shorthand method for constructing a {@link RelyingPartyConfiguration} with an activation condition
- * based on an {@link EntityAttributesPredicate}.
- *
- * @param candidates the candidate rules
- * @param trim true iff tag values in metadata should be trimmed before comparison
- * @param matchAll true iff all the candidate rules are required to match
- *
- * @return a default-constructed configuration with the appropriate condition set
- */
- @Nonnull public static RelyingPartyConfiguration byTag(@Nonnull final Collection<Candidate> candidates,
- final boolean trim, final boolean matchAll) {
- Constraint.isNotNull(candidates, "Candidate list cannot be null");
-
- // We adapt an OpenSAML Predicate applying to an EntityDescriptor by indirecting the lookup of the
- // EntityDescriptor to a lookup sequence of PRC -> RPC -> SAMLMetadataContext -> EntityDescriptor.
-
- final StrategyIndirectedPredicate<ProfileRequestContext,EntityDescriptor> indirectPredicate =
- new StrategyIndirectedPredicate<>(
- new EntityDescriptorLookupFunction().compose(new SAMLMetadataContextLookupFunction()),
- new EntityAttributesPredicate(candidates, trim, matchAll));
-
- final DelegatingRelyingPartyConfiguration config = new DelegatingRelyingPartyConfiguration();
- config.setActivationCondition(indirectPredicate);
-
- return config;
- }
-
- /**
- * A shorthand method for constructing a {@link RelyingPartyConfiguration} with an activation condition
- * based on a {@link MappedEntityAttributesPredicate}.
- *
- * @param candidates the candidate rules
- * @param trim true iff tag values in metadata should be trimmed before comparison
- * @param matchAll true iff all the candidate rules are required to match
- *
- * @return a default-constructed configuration with the appropriate condition set
- */
- @Nonnull public static RelyingPartyConfiguration byMappedTag(@Nonnull final Collection<Candidate> candidates,
- final boolean trim, final boolean matchAll) {
- Constraint.isNotNull(candidates, "Candidate list cannot be null");
-
- // We adapt an OpenSAML Predicate applying to an EntityDescriptor by indirecting the lookup of the
- // EntityDescriptor to a lookup sequence of PRC -> RPC -> SAMLMetadataContext -> EntityDescriptor.
-
- final StrategyIndirectedPredicate<ProfileRequestContext,EntityDescriptor> indirectPredicate =
- new StrategyIndirectedPredicate<>(
- new EntityDescriptorLookupFunction().compose(new SAMLMetadataContextLookupFunction()),
- new MappedEntityAttributesPredicate(candidates, trim, matchAll));
-
- final DelegatingRelyingPartyConfiguration config = new DelegatingRelyingPartyConfiguration();
- config.setActivationCondition(indirectPredicate);
-
- return config;
- }
-
-}
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list