[java-plugin-shibd-saml] branch main updated: JSHIBD-7 - Decompose Application layer to avoid protocol dependencies
Codeberg
noreply at shibboleth.net
Thu Feb 5 19:36:39 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-saml.
View the commit online:
https://codeberg.org/Shibboleth/java-plugin-shibd-saml/commit/938713b955db6bfe205183d8f41c67607d7c078e
The following commit(s) were added to refs/heads/main by this push:
new 938713b JSHIBD-7 - Decompose Application layer to avoid protocol dependencies
938713b is described below
commit 938713b955db6bfe205183d8f41c67607d7c078e
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Thu Feb 5 14:32:20 2026 -0500
JSHIBD-7 - Decompose Application layer to avoid protocol dependencies
https://shibboleth.atlassian.net/browse/JSHIBD-7
Implement SAML-specific ProtocolSupportService code.
Migrate MetadataResolver dependencies to new API.
---
.../saml2/BasicSAML2ProtocolSupportService.java | 62 +++++++++++++++++
.../sp/saml/saml2/SAML2ProtocolSupportService.java | 41 +++++++++++
.../net/shibboleth/sp/saml/saml2/package-info.java | 18 +++++
.../shibboleth/idp/flows/sp/saml2-common-beans.xml | 2 +-
.../net/shibboleth/sp/service/agent/postconfig.xml | 3 +-
sp-saml-impl/pom.xml | 5 ++
.../ApplicationMetadataResolverLookupFunction.java | 79 ++++++++++++++++++++++
.../saml2/profile/impl/ExtractSAMLAttributes.java | 26 +++++--
8 files changed, 227 insertions(+), 9 deletions(-)
diff --git a/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/BasicSAML2ProtocolSupportService.java b/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/BasicSAML2ProtocolSupportService.java
new file mode 100644
index 0000000..91b416a
--- /dev/null
+++ b/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/BasicSAML2ProtocolSupportService.java
@@ -0,0 +1,62 @@
+/*
+ * 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.saml.saml2;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.saml.metadata.resolver.MetadataResolver;
+
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.service.ReloadableService;
+import net.shibboleth.sp.BasicProtocolSupportService;
+
+/**
+ * Basic implementation of {@link SAML2ProtocolSupportService}.
+ */
+public class BasicSAML2ProtocolSupportService extends BasicProtocolSupportService
+ implements SAML2ProtocolSupportService {
+
+ /** Metadata source. */
+ @NonnullAfterInit private ReloadableService<MetadataResolver> metadataResolver;
+
+
+ /** [{@inheritDoc} */
+ @NonnullAfterInit public ReloadableService<MetadataResolver> getMetadataResolver() {
+ return metadataResolver;
+ }
+
+ /**
+ * Sets the {@link MetadataResolver} to use.
+ *
+ * @param service metadata resolver service
+ */
+ public void setMetadataResolver(@Nonnull final ReloadableService<MetadataResolver> service) {
+ checkSetterPreconditions();
+
+ metadataResolver = Constraint.isNotNull(service, "MetadataResolver service cannot be null");
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+
+ if (metadataResolver == null) {
+ throw new ComponentInitializationException("MetadataResolver cannot be null");
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/SAML2ProtocolSupportService.java b/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/SAML2ProtocolSupportService.java
new file mode 100644
index 0000000..21b7cee
--- /dev/null
+++ b/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/SAML2ProtocolSupportService.java
@@ -0,0 +1,41 @@
+/*
+ * 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.saml.saml2;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.saml.metadata.resolver.MetadataResolver;
+
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.service.ReloadableService;
+import net.shibboleth.sp.ProtocolSupportService;
+
+/**
+ * SAML 2 subinterface of {@link ProtocolSupportService} to any add SAML-specific features or services.
+ */
+public interface SAML2ProtocolSupportService extends ProtocolSupportService {
+
+ /** Key of map entry for this subtype. */
+ @Nonnull @NotEmpty static String PROTOCOL_ID = "SAML2";
+
+ /**
+ * Gets the default {@link MetadataResolver} service to use.
+ *
+ * @return service to use
+ */
+ @NonnullAfterInit ReloadableService<MetadataResolver> getMetadataResolver();
+
+}
\ No newline at end of file
diff --git a/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/package-info.java b/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/package-info.java
new file mode 100644
index 0000000..093a696
--- /dev/null
+++ b/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/package-info.java
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
+
+/**
+ * Supporting APIs and classes for SAML 2.0 protocol support in the SP Hub.
+ */
+package net.shibboleth.sp.saml.saml2;
\ No newline at end of file
diff --git a/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/saml2-common-beans.xml b/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/saml2-common-beans.xml
index 41434c7..75423c6 100644
--- a/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/saml2-common-beans.xml
+++ b/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/saml2-common-beans.xml
@@ -39,7 +39,7 @@
<constructor-arg name="messageHandler">
<bean class="org.opensaml.saml.common.binding.impl.SAMLMetadataLookupHandler" scope="prototype">
<property name="roleDescriptorResolverLookupStrategy">
- <bean class="net.shibboleth.sp.profile.context.navigate.messaging.ApplicationMetadataResolverLookupFunction" />
+ <bean class="net.shibboleth.sp.saml.saml2.profile.impl.ApplicationMetadataResolverLookupFunction" />
</property>
</bean>
</constructor-arg>
diff --git a/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/sp/service/agent/postconfig.xml b/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/sp/service/agent/postconfig.xml
index 1bae617..3922a3a 100644
--- a/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/sp/service/agent/postconfig.xml
+++ b/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/sp/service/agent/postconfig.xml
@@ -18,9 +18,10 @@
<!-- <import resource="agents-system-mddriven.xml" /> -->
<!-- Auto-wired protocol service support bean for use by parent plugin. -->
- <bean class="net.shibboleth.sp.BasicProtocolSupportService"
+ <bean class="net.shibboleth.sp.saml.saml2.BasicSAML2ProtocolSupportService"
p:id="SAML2"
p:order="%{sp.saml.relativeOrder:1}"
+ p:metadataResolver-ref="shibboleth.MetadataResolverService"
p:sessionInitiators="saml2"
p:tokenConsumers="#{{ 'saml2/post', 'saml2/post-simplesign', 'saml2/artifact' }}">
<property name="defaultProfileConfigurations">
diff --git a/sp-saml-impl/pom.xml b/sp-saml-impl/pom.xml
index c679775..e6be3ba 100644
--- a/sp-saml-impl/pom.xml
+++ b/sp-saml-impl/pom.xml
@@ -82,6 +82,11 @@
<artifactId>shib-metadata-api</artifactId>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>${shib-metadata.groupId}</groupId>
+ <artifactId>shib-metadata-impl</artifactId>
+ <scope>provided</scope>
+ </dependency>
<dependency>
<groupId>${opensaml.groupId}</groupId>
diff --git a/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/ApplicationMetadataResolverLookupFunction.java b/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/ApplicationMetadataResolverLookupFunction.java
new file mode 100644
index 0000000..87e644d
--- /dev/null
+++ b/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/ApplicationMetadataResolverLookupFunction.java
@@ -0,0 +1,79 @@
+/*
+ * 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.saml.saml2.profile.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.saml.metadata.resolver.MetadataResolver;
+import org.opensaml.saml.metadata.resolver.RoleDescriptorResolver;
+import org.opensaml.saml.metadata.resolver.impl.PredicateRoleDescriptorResolver;
+import org.slf4j.Logger;
+
+import net.shibboleth.idp.saml.metadata.impl.ReloadableMetadataResolver;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.sp.Application;
+import net.shibboleth.sp.context.AgentRequestContext;
+import net.shibboleth.sp.profile.context.navigate.messaging.AbstractAgentRequestLookupFunction;
+import net.shibboleth.sp.saml.saml2.SAML2ProtocolSupportService;
+
+/**
+ * Locates the {@link MetadataResolver} associated with the {@link Application} making an agent request,
+ * and wraps it in a {@link RoleDescriptorResolver}.
+ */
+public class ApplicationMetadataResolverLookupFunction
+ extends AbstractAgentRequestLookupFunction<RoleDescriptorResolver> {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(ApplicationMetadataResolverLookupFunction.class);
+
+ /** {@inheritDoc} */
+ @Nullable public RoleDescriptorResolver apply(@Nullable final MessageContext input) {
+ final AgentRequestContext arc = getAgentRequestContext(input);
+ if (arc != null) {
+ final Application application = arc.getApplication();
+ if (application != null) {
+ try {
+ final SAML2ProtocolSupportService supportService =
+ application.getProtocolSupportService(SAML2ProtocolSupportService.PROTOCOL_ID,
+ SAML2ProtocolSupportService.class);
+ if (supportService != null) {
+ final ReloadableMetadataResolver metadataResolver =
+ new ReloadableMetadataResolver(supportService.getMetadataResolver());
+ metadataResolver.setId(application.getId() + " MetadataResolver");
+ metadataResolver.initialize();
+
+ final PredicateRoleDescriptorResolver roleResolver =
+ new PredicateRoleDescriptorResolver(metadataResolver);
+ roleResolver.initialize();
+
+ return roleResolver;
+ } else {
+ log.warn("Application did not supply a SAML 2 ProtocolSupportService instance");
+ }
+ } catch (final ComponentInitializationException e) {
+ log.error("Exception wrapping Application-supplied MetadataResolver for use", e);
+ }
+ } else {
+ log.warn("Application was not available to acquire necessary services");
+ }
+ }
+
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/ExtractSAMLAttributes.java b/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/ExtractSAMLAttributes.java
index 8d6dbf0..7a327df 100644
--- a/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/ExtractSAMLAttributes.java
+++ b/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/ExtractSAMLAttributes.java
@@ -86,6 +86,7 @@ import net.shibboleth.shared.service.ServiceException;
import net.shibboleth.shared.service.ServiceableComponent;
import net.shibboleth.sp.Application;
import net.shibboleth.sp.profile.AbstractApplicationAction;
+import net.shibboleth.sp.saml.saml2.SAML2ProtocolSupportService;
import net.shibboleth.sp.saml.saml2.context.SAMLTokenContext;
import net.shibboleth.sp.saml.saml2.profile.config.BrowserSSOProfileConfiguration;
@@ -480,15 +481,26 @@ public class ExtractSAMLAttributes extends AbstractApplicationAction {
populateFilterContext(profileRequestContext, filterContext);
try (final ServiceableComponent<AttributeFilter> filterComponent =
- ensureApplication().getAttributeFilter().getServiceableComponent();
- final ServiceableComponent<MetadataResolver> metadataResolverComponent =
- ensureApplication().getMetadataResolver().getServiceableComponent()) {
+ ensureApplication().getAttributeFilter().getServiceableComponent()) {
- // Populate here for locking scope.
- filterContext.setMetadataResolver(metadataResolverComponent.getComponent());
+ // We have to fork here based on whether we can access a MetadataResolver.
+
+ final SAML2ProtocolSupportService supportService = ensureApplication().getProtocolSupportService(
+ SAML2ProtocolSupportService.PROTOCOL_ID, SAML2ProtocolSupportService.class);
+ if (supportService != null) {
+ try (final ServiceableComponent<MetadataResolver> metadataComponent =
+ supportService.getMetadataResolver().getServiceableComponent()) {
+ filterContext.setMetadataResolver(metadataComponent.getComponent());
+ final AttributeFilter filter = filterComponent.getComponent();
+ filter.filterAttributes(filterContext);
+ } catch (final ServiceException e) {
+ log.error("{} Invalid MetadataResolver configuration", getLogPrefix(), e);
+ }
+ } else {
+ final AttributeFilter filter = filterComponent.getComponent();
+ filter.filterAttributes(filterContext);
+ }
- final AttributeFilter filter = filterComponent.getComponent();
- filter.filterAttributes(filterContext);
filterContext.removeFromParent();
attributeContext.setIdPAttributes(filterContext.getFilteredIdPAttributes());
} catch (final AttributeFilterException e) {
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list