[java-plugin-shibd-oidc] branch main updated: JSHIBDOIDC-11 - Fix provider metadata handling
Codeberg
noreply at shibboleth.net
Fri Feb 6 11:52:41 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-oidc.
View the commit online:
https://codeberg.org/Shibboleth/java-plugin-shibd-oidc/commit/096642eb6aecd0ae2109c2636bfcacc19e02add8
The following commit(s) were added to refs/heads/main by this push:
new 096642e JSHIBDOIDC-11 - Fix provider metadata handling
096642e is described below
commit 096642eb6aecd0ae2109c2636bfcacc19e02add8
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Fri Feb 6 11:52:31 2026 +0000
JSHIBDOIDC-11 - Fix provider metadata handling
- Based on the new work in
https://shibboleth.atlassian.net/browse/JSHIBD-7 , added an OIDC
specific protocol support service.
- Added support for OpenID Provider metadata lookups using the
configurable provider resolver.
- Obtain the metadata resolver from the Application's Protocol Support
Service.
https://shibboleth.atlassian.net/browse/JSHIBDOIDC-11
---
.../sp/oidc/BasicOIDCProtocolSupportService.java | 61 ++++++++++++++++++++++
.../sp/oidc/OIDCProtocolSupportService.java | 40 ++++++++++++++
.../java/net/shibboleth/sp/oidc/package-info.java | 18 +++++++
.../META-INF/net.shibboleth.idp/postconfig.xml | 11 ++--
.../idp/flows/sp/consumer/oidc/oidc-beans.xml | 11 ----
.../idp/flows/sp/initiator/oidc/oidc-beans.xml | 11 ----
.../shibboleth/idp/flows/sp/oidc-common-beans.xml | 14 +++++
.../net/shibboleth/sp/service/agent/postconfig.xml | 3 +-
.../module/conf/oidc-metadata-providers-system.xml | 61 ++++++++++------------
.../oidc/flows/OIDCSessionInitiatorFlowTest.java | 60 +++++++++++++++++++++
.../sp/oidc/flows/OIDCTokenConsumerFlowTest.java | 25 ++++++++-
.../idp/module/conf/sp/oidc-metadata-providers.xml | 34 ++++++++++++
.../idp/module/conf/sp/oidc-test-agents.xml | 12 ++---
.../ApplicationMetadataResolverLookupFunction.java | 51 ++++++++----------
.../sp/oidc/profile/impl/ExtractOIDCClaims.java | 28 +++++++---
15 files changed, 328 insertions(+), 112 deletions(-)
diff --git a/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/BasicOIDCProtocolSupportService.java b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/BasicOIDCProtocolSupportService.java
new file mode 100644
index 0000000..c3cf21e
--- /dev/null
+++ b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/BasicOIDCProtocolSupportService.java
@@ -0,0 +1,61 @@
+/*
+ * 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.oidc;
+
+import javax.annotation.Nonnull;
+
+import net.shibboleth.oidc.metadata.ProviderMetadataResolver;
+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;
+
+/**
+ * A basic implementation of {@link OIDCProtocolSupportService}.
+ */
+public class BasicOIDCProtocolSupportService extends BasicProtocolSupportService implements OIDCProtocolSupportService {
+
+ /** Metadata source. */
+ @NonnullAfterInit private ReloadableService<ProviderMetadataResolver> metadataResolver;
+
+ /** [{@inheritDoc} */
+ @NonnullAfterInit
+ public ReloadableService<ProviderMetadataResolver> getMetadataResolver() {
+ return metadataResolver;
+ }
+
+ /**
+ * Sets the {@link ProviderMetadataResolver} to use.
+ *
+ * @param service
+ * metadata resolver service
+ */
+ public void setMetadataResolver(@Nonnull final ReloadableService<ProviderMetadataResolver> service) {
+ checkSetterPreconditions();
+
+ metadataResolver = Constraint.isNotNull(service, "ProviderMetadataResolver service cannot be null");
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+
+ if (metadataResolver == null) {
+ throw new ComponentInitializationException("ProviderMetadataResolver cannot be null");
+ }
+ }
+
+}
diff --git a/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/OIDCProtocolSupportService.java b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/OIDCProtocolSupportService.java
new file mode 100644
index 0000000..fe178e5
--- /dev/null
+++ b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/OIDCProtocolSupportService.java
@@ -0,0 +1,40 @@
+/*
+ * 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.oidc;
+
+import javax.annotation.Nonnull;
+
+import net.shibboleth.oidc.metadata.ProviderMetadataResolver;
+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;
+
+/**
+ * OIDC subinterface of {@link ProtocolSupportService} to add any OIDC-specific features or services.
+ */
+public interface OIDCProtocolSupportService extends ProtocolSupportService {
+
+ /** Key of the map entry for this subtype. */
+ @Nonnull @NotEmpty static String PROTOCOL_ID = "OIDC";
+
+ /**
+ * Gets the default {@link ProviderMetadataResolver} service to use.
+ *
+ * @return service to use
+ */
+ @NonnullAfterInit ReloadableService<ProviderMetadataResolver> getMetadataResolver();
+
+}
diff --git a/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/package-info.java b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/package-info.java
new file mode 100644
index 0000000..a72d8e5
--- /dev/null
+++ b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/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 OIDC protocol support in the SP Hub.
+ */
+package net.shibboleth.sp.oidc;
\ No newline at end of file
diff --git a/sp-oidc-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml b/sp-oidc-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
index 6a74492..2b2cdb3 100644
--- a/sp-oidc-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
+++ b/sp-oidc-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
@@ -89,12 +89,6 @@
</property>
</bean>
-
- <!-- OpenID Provider information resolver service beans. -->
- <bean id="shibboleth.authn.oidc.rp.ProviderMetadataResolver"
- class="net.shibboleth.oidc.metadata.impl.ReloadingProviderMetadataProvider"
- c:resolverService-ref="shibboleth.ProviderMetadataResolverService" />
-
<bean id="shibboleth.ProviderMetadataResolverService"
class="net.shibboleth.shared.spring.service.ReloadableSpringService"
p:serviceConfigurations-ref="ExtendedProviderMetadataResolverResources"
@@ -109,8 +103,9 @@
</constructor-arg>
</bean>
- <!-- <util:list id="shibboleth.DefaultProviderMetadataResolverResources"> <value>conditional:%{idp.home}/conf/authn/oidc-metadata-providers.xml</value>
- </util:list> -->
+ <util:list id="shibboleth.DefaultProviderMetadataResolverResources">
+ <value>conditional:%{idp.home}/conf/sp/oidc-metadata-providers.xml</value>
+ </util:list>
<!-- Auto-append system config file to resource set. -->
<bean id="ExtendedProviderMetadataResolverResources"
diff --git a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/oidc/oidc-beans.xml b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/oidc/oidc-beans.xml
index e487de8..21bff5c 100644
--- a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/oidc/oidc-beans.xml
+++ b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/oidc/oidc-beans.xml
@@ -74,17 +74,6 @@
class="net.shibboleth.sp.oidc.profile.impl.ValidateResponseState"
p:nonceTokenLookupStrategy-ref="NonceFromStateLookup" />
- <bean id="ProviderMetadataLookup" parent="WebFlowInboundMessageHandlerAdaptor">
- <constructor-arg name="messageHandler"> <!-- TODO Copied over -->
- <bean class="net.shibboleth.sp.oidc.metadata.impl.OIDCProviderMetadataLookupHandler"
- scope="prototype">
- <property name="ProviderMetadataResolverLookupStrategy">
- <bean class="net.shibboleth.sp.oidc.metadata.impl.ApplicationMetadataResolverLookupFunction" /> <!-- TODO Needs to be core-sp version -->
- </property>
- </bean>
- </constructor-arg>
- </bean>
-
<bean id="InitializeRelyingPartyContextFromOIDCPeer"
class="net.shibboleth.sp.oidc.profile.impl.InitializeRelyingPartyContextFromOIDCPeer" scope="prototype" />
diff --git a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/oidc/oidc-beans.xml b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/oidc/oidc-beans.xml
index a807a85..2b03136 100644
--- a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/oidc/oidc-beans.xml
+++ b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/oidc/oidc-beans.xml
@@ -28,17 +28,6 @@
p:relyingPartyLookupStrategy-ref="shibboleth.RelyingPartyIdLookup.Simple">
</bean>
- <bean id="ProviderMetadataLookup" parent="WebFlowInboundMessageHandlerAdaptor">
- <constructor-arg name="messageHandler"> <!-- TODO Copied over -->
- <bean class="net.shibboleth.sp.oidc.metadata.impl.OIDCProviderMetadataLookupHandler"
- scope="prototype">
- <property name="ProviderMetadataResolverLookupStrategy">
- <bean class="net.shibboleth.sp.oidc.metadata.impl.ApplicationMetadataResolverLookupFunction" /> <!-- TODO Needs to be core-sp version -->
- </property>
- </bean>
- </constructor-arg>
- </bean>
-
<bean id="InitializeRelyingPartyContextFromOIDCPeer"
class="net.shibboleth.sp.oidc.profile.impl.InitializeRelyingPartyContextFromOIDCPeer" scope="prototype" />
diff --git a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/oidc-common-beans.xml b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/oidc-common-beans.xml
index e2992a7..e264dde 100644
--- a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/oidc-common-beans.xml
+++ b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/oidc-common-beans.xml
@@ -177,5 +177,19 @@
<ref bean="shibboleth.MessageContextLookup.Inbound" />
</constructor-arg>
</bean>
+
+ <!-- Common Actions -->
+
+ <bean id="ProviderMetadataLookup" parent="WebFlowInboundMessageHandlerAdaptor" scope="prototype">
+ <constructor-arg name="messageHandler"> <!-- TODO move into common beans? -->
+ <bean class="net.shibboleth.sp.oidc.metadata.impl.OIDCProviderMetadataLookupHandler"
+ scope="prototype">
+ <property name="ProviderMetadataResolverLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.impl.ApplicationMetadataResolverLookupFunction" />
+ </property>
+ </bean>
+ </constructor-arg>
+ </bean>
+
</beans>
diff --git a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/sp/service/agent/postconfig.xml b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/sp/service/agent/postconfig.xml
index a4dead3..607b60e 100644
--- a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/sp/service/agent/postconfig.xml
+++ b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/sp/service/agent/postconfig.xml
@@ -18,10 +18,11 @@
<!-- <import resource="relying-party-mddriven.xml" /> -->
<!-- Auto-wired protocol service support bean for use by parent plugin. -->
- <bean class="net.shibboleth.sp.BasicProtocolSupportService"
+ <bean class="net.shibboleth.sp.oidc.BasicOIDCProtocolSupportService"
p:id="OIDC"
p:order="%{sp.oidc.relativeOrder:1}"
p:sessionInitiators="oidc"
+ p:metadataResolver-ref="shibboleth.ProviderMetadataResolverService"
p:tokenConsumers="#{{'oidc/code/query', 'oidc/code/post'}}">
<property name="defaultProfileConfigurations">
<list>
diff --git a/sp-oidc-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/oidc-metadata-providers-system.xml b/sp-oidc-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/oidc-metadata-providers-system.xml
index 5092369..c7eb218 100644
--- a/sp-oidc-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/oidc-metadata-providers-system.xml
+++ b/sp-oidc-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/oidc-metadata-providers-system.xml
@@ -9,81 +9,76 @@
default-init-method="initialize" default-destroy-method="destroy" default-lazy-init="true">
- <!-- Loaded by the postconfig.xml file as global beans -->
-
- <!-- TODO bean IDs are all wrong -->
- <!-- TODO is this in the correct place in the tree -->
-
- <bean id="shibboleth.authn.oidc.rp.ProviderMetadataProvider" lazy-init="false"
+ <bean id="shibboleth.sp.ProviderMetadataProvider" lazy-init="false"
class="net.shibboleth.oidc.metadata.ProviderMetadataProviderContainer"
- p:embeddedResolver-ref="shibboleth.authn.oidc.rp.ChainingProviderMetadataResolver">
+ p:embeddedResolver-ref="shibboleth.sp.ChainingProviderMetadataResolver">
</bean>
- <bean id="shibboleth.authn.oidc.rp.ChainingProviderMetadataResolver"
+ <bean id="shibboleth.sp.ChainingProviderMetadataResolver"
class="net.shibboleth.oidc.metadata.impl.ChainingProviderMetadataResolver" p:id="InternalEmbeddedChainResolver"
- p:resolvers="#{getObject('shibboleth.authn.oidc.rp.ProviderMetadataResolvers')}" />
+ p:resolvers="#{getObject('shibboleth.sp.ProviderMetadataResolvers')}" />
<!-- abstract beans for the user space config to extend -->
- <bean id="shibboleth.authn.oidc.rp.OIDCProviderMetadataResolver" abstract="true"
+ <bean id="shibboleth.sp.OIDCProviderMetadataResolver" abstract="true"
class="net.shibboleth.oidc.metadata.impl.OIDCProviderMetadataResolver" />
- <bean id="shibboleth.authn.oidc.rp.DefaultHTTPProviderConfigurationMetadataFetchingStrategy"
+ <bean id="shibboleth.sp.DefaultHTTPProviderConfigurationMetadataFetchingStrategy"
class="net.shibboleth.oidc.metadata.impl.HTTPProviderConfigurationFetchingStrategy"
- c:client-ref="shibboleth.InternalHttpClient"
- c:handler-ref="shibboleth.authn.oidc.rp.DefaultHTTProviderConfigurationMetadataResponseHandler"
- p:wellKnownLocationCompositionStrategy="#{getObject('shibboleth.authn.oidc.rp.WellKnownLocationCompositionStrategy')}"/>
+ c:client="#{getObject('%{sp.oidc.HttpClient:}') ?: getObject('shibboleth.InternalHttpClient')}"
+ c:handler-ref="shibboleth.sp.DefaultHTTProviderConfigurationMetadataResponseHandler"
+ p:wellKnownLocationCompositionStrategy="#{getObject('shibboleth.sp.WellKnownLocationCompositionStrategy')}"/>
- <bean id="shibboleth.authn.oidc.rp.DefaultHTTProviderConfigurationMetadataResponseHandler"
+ <bean id="shibboleth.sp.DefaultHTTProviderConfigurationMetadataResponseHandler"
class="net.shibboleth.oidc.metadata.impl.HTTPProviderConfigurationFetchingStrategy.OIDCProviderMetadataResponseHandler" />
<!-- Cache builder specifications -->
<bean id="cacheFactory" class="net.shibboleth.oidc.metadata.cache.impl.MetadataCacheBuilder$Builder"/>
- <bean id="shibboleth.authn.oidc.rp.CacheBuilder" factory-bean="cacheFactory" factory-method="build"
+ <bean id="shibboleth.sp.CacheBuilder" factory-bean="cacheFactory" factory-method="build"
abstract="true"/>
<bean class="net.shibboleth.oidc.metadata.cache.impl.BatchMetadataCacheBuilderSpec"
- id="shibboleth.authn.oidc.rp.BaseProviderBatchCacheBuilderSpec" abstract="true"
- p:parsingStrategy-ref="shibboleth.authn.oidc.rp.DefaultOIDCProviderMetadataParsingStrategy"
- p:criteriaToIdentifierStrategy-ref="shibboleth.authn.oidc.rp.DefaultOIDCProviderMetadataCriteriaToIdentifierStrategy"
- p:sourceMetadataExpiryStrategy-ref="shibboleth.authn.oidc.rp.DefaultODICProviderSourceMetadataExpirationTimeStrategy"
- p:identifierExtractionStrategy-ref="shibboleth.authn.oidc.rp.DefaultOIDCProviderMetadataIdentifierExtractionStrategy"/>
+ id="shibboleth.sp.BaseProviderBatchCacheBuilderSpec" abstract="true"
+ p:parsingStrategy-ref="shibboleth.sp.DefaultOIDCProviderMetadataParsingStrategy"
+ p:criteriaToIdentifierStrategy-ref="shibboleth.sp.DefaultOIDCProviderMetadataCriteriaToIdentifierStrategy"
+ p:sourceMetadataExpiryStrategy-ref="shibboleth.sp.DefaultODICProviderSourceMetadataExpirationTimeStrategy"
+ p:identifierExtractionStrategy-ref="shibboleth.sp.DefaultOIDCProviderMetadataIdentifierExtractionStrategy"/>
<bean class="net.shibboleth.oidc.metadata.cache.impl.DynamicMetadataCacheBuilderSpec"
- id="shibboleth.authn.oidc.rp.BaseProviderDynamicCacheBuilderSpec" abstract="true"
- p:fetchStrategy-ref="shibboleth.authn.oidc.rp.DefaultHTTPProviderConfigurationMetadataFetchingStrategy"
- p:criteriaToIdentifierStrategy-ref="shibboleth.authn.oidc.rp.DefaultOIDCProviderMetadataCriteriaToIdentifierStrategy"
- p:metadataExpirationTimeStrategy-ref="shibboleth.authn.oidc.rp.DefaultODICProviderMetadataExpirationTimeStrategy"
- p:identifierExtractionStrategy-ref="shibboleth.authn.oidc.rp.DefaultOIDCProviderMetadataIdentifierExtractionStrategy"
+ id="shibboleth.sp.BaseProviderDynamicCacheBuilderSpec" abstract="true"
+ p:fetchStrategy-ref="shibboleth.sp.DefaultHTTPProviderConfigurationMetadataFetchingStrategy"
+ p:criteriaToIdentifierStrategy-ref="shibboleth.sp.DefaultOIDCProviderMetadataCriteriaToIdentifierStrategy"
+ p:metadataExpirationTimeStrategy-ref="shibboleth.sp.DefaultODICProviderMetadataExpirationTimeStrategy"
+ p:identifierExtractionStrategy-ref="shibboleth.sp.DefaultOIDCProviderMetadataIdentifierExtractionStrategy"
/>
<!-- Common parents for cache strategy implementations -->
- <bean id="shibboleth.authn.oidc.rp.ProviderConfigurationMetadataFileLoadingStrategy"
+ <bean id="shibboleth.sp.ProviderConfigurationMetadataFileLoadingStrategy"
class="net.shibboleth.oidc.metadata.cache.impl.DefaultFileLoadingStrategy" abstract="true"/>
<!-- Common implementation strategies for cache implementations -->
- <bean id="shibboleth.authn.oidc.rp.DefaultOIDCProviderMetadataParsingStrategy" scope="prototype"
+ <bean id="shibboleth.sp.DefaultOIDCProviderMetadataParsingStrategy" scope="prototype"
class="net.shibboleth.oidc.metadata.cache.impl.DefaultOIDCProviderMetadataParsingStrategy" />
- <bean id="shibboleth.authn.oidc.rp.DefaultMapParsingStrategy" scope="prototype"
+ <bean id="shibboleth.sp.DefaultMapParsingStrategy" scope="prototype"
class="net.shibboleth.oidc.metadata.cache.impl.DefaultJSONMapParsingStrategy" />
- <bean id="shibboleth.authn.oidc.rp.DefaultODICProviderMetadataExpirationTimeStrategy" scope="prototype"
+ <bean id="shibboleth.sp.DefaultODICProviderMetadataExpirationTimeStrategy" scope="prototype"
class="net.shibboleth.oidc.metadata.cache.impl.DefaultOIDCProviderMetadataExpirationTimeStrategy"/>
- <bean id="shibboleth.authn.oidc.rp.DefaultODICProviderSourceMetadataExpirationTimeStrategy" scope="prototype"
+ <bean id="shibboleth.sp.DefaultODICProviderSourceMetadataExpirationTimeStrategy" scope="prototype"
class="net.shibboleth.oidc.metadata.cache.impl.DefaultSourceMetadataExpirationTimeStrategy"
c:duration="PT10M" />
- <bean id="shibboleth.authn.oidc.rp.DefaultOIDCProviderMetadataIdentifierExtractionStrategy" scope="prototype"
+ <bean id="shibboleth.sp.DefaultOIDCProviderMetadataIdentifierExtractionStrategy" scope="prototype"
class="net.shibboleth.oidc.metadata.cache.impl.DefaultOIDCProviderMetadataIdentifierExtractionStrategy" />
- <bean id="shibboleth.authn.oidc.rp.DefaultOIDCProviderMetadataCriteriaToIdentifierStrategy" scope="prototype"
+ <bean id="shibboleth.sp.DefaultOIDCProviderMetadataCriteriaToIdentifierStrategy" scope="prototype"
class="net.shibboleth.oidc.metadata.cache.impl.DefaultOIDCProviderMetadataCriteriaToIdentifierStrategy" />
diff --git a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCSessionInitiatorFlowTest.java b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCSessionInitiatorFlowTest.java
index ad0a75a..9e8405c 100644
--- a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCSessionInitiatorFlowTest.java
+++ b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCSessionInitiatorFlowTest.java
@@ -17,6 +17,7 @@ package net.shibboleth.sp.oidc.flows;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.fail;
import java.io.IOException;
import java.net.URI;
@@ -28,22 +29,31 @@ import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import org.apache.hc.client5.http.classic.HttpClient;
+import org.apache.hc.core5.http.io.HttpClientResponseHandler;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.mockito.Mockito;
import org.opensaml.messaging.decoder.MessageDecodingException;
import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.saml.common.binding.SAMLBindingSupport;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.io.ClassPathResource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.util.ObjectUtils;
import org.springframework.webflow.engine.impl.FlowExecutionImpl;
import org.springframework.webflow.executor.FlowExecutionResult;
import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.PlainJWT;
import com.nimbusds.jwt.SignedJWT;
import com.nimbusds.oauth2.sdk.ParseException;
+import com.nimbusds.oauth2.sdk.util.JSONObjectUtils;
import com.nimbusds.openid.connect.sdk.AuthenticationRequest;
+import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
import net.shibboleth.idp.spring.IdPPropertiesApplicationContextInitializer;
import net.shibboleth.idp.test.PreferFileSystemApplicationContextInitializer;
@@ -80,6 +90,12 @@ public class OIDCSessionInitiatorFlowTest extends AbstractSPFlowTest {
/** REDIRECT URI. */
@Nonnull public static final String RESPONSE_URL = "https://sp.example.org/Shibboleth.sso/callback";
+
+ /** The mocked HttpClient to use when responding to Token and UserInfo requests.*/
+ private HttpClient httpClient;
+
+ /** The OP metadata to use.*/
+ private OIDCProviderMetadata metadata;
/** Constructor. */
@@ -87,6 +103,50 @@ public class OIDCSessionInitiatorFlowTest extends AbstractSPFlowTest {
super(FLOW_ID);
}
+ /**
+ * Pre-test work.
+ *
+ * @throws Exception on error
+ */
+ @BeforeMethod
+ public void beforeMethod() throws Exception {
+ setDefaultAuth();
+ final ApplicationContext applicationContext2 = applicationContext;
+ if (applicationContext2 != null) {
+ httpClient = applicationContext2.getBean("Mock.HttpClient", HttpClient.class);
+ } else {
+ fail("Mocked Http Client could not be found");
+ }
+ if (httpClient == null) {
+ fail("Mocked Http Client could not be found");
+ }
+ // Add a default metadata response
+ final var metadataFromFile = new ClassPathResource("metadata/openid-configuration.json");
+ final String json = new String(metadataFromFile.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
+ metadata = OIDCProviderMetadata.parse(JSONObjectUtils.parse(json));
+ mockProviderMetadataEndpoint(metadata);
+
+ }
+
+ /**
+ * Mock OpenID Provider configuration (metadata) endpoint.
+ *
+ * @param tokenResponse the token response
+ * @param userInfoResponse the user info response
+ *
+ * @throws IOException on error.
+ */
+ private void mockProviderMetadataEndpoint(final OIDCProviderMetadata metadata) throws IOException {
+
+ Mockito.when(httpClient.execute(
+ Mockito.argThat(req -> req != null && req.getRequestUri().toString()
+ .contains(".well-known/openid-configuration")),
+ Mockito.any(HttpContext.class),
+ Mockito.any(HttpClientResponseHandler.class)))
+ .thenReturn(metadata);
+
+ }
+
/**
* Basic flow test.
*
diff --git a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java
index cc58fb5..cf2062c 100644
--- a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java
+++ b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java
@@ -51,6 +51,7 @@ import org.opensaml.saml.saml2.core.NameIDType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
+import org.springframework.core.io.ClassPathResource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.webflow.executor.FlowExecutionResult;
@@ -72,11 +73,13 @@ import com.nimbusds.oauth2.sdk.id.State;
import com.nimbusds.oauth2.sdk.token.AccessToken;
import com.nimbusds.oauth2.sdk.token.BearerAccessToken;
import com.nimbusds.oauth2.sdk.token.RefreshToken;
+import com.nimbusds.oauth2.sdk.util.JSONObjectUtils;
import com.nimbusds.openid.connect.sdk.AuthenticationErrorResponse;
import com.nimbusds.openid.connect.sdk.AuthenticationSuccessResponse;
import com.nimbusds.openid.connect.sdk.OIDCTokenResponse;
import com.nimbusds.openid.connect.sdk.UserInfoSuccessResponse;
import com.nimbusds.openid.connect.sdk.claims.UserInfo;
+import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
import com.nimbusds.openid.connect.sdk.token.OIDCTokens;
import net.minidev.json.JSONObject;
@@ -125,15 +128,22 @@ public class OIDCTokenConsumerFlowTest extends AbstractSPFlowTest {
/** The mocked HttpClient to use when responding to Token and UserInfo requests.*/
private HttpClient httpClient;
+
+ /** The OP metadata to use.*/
+ private OIDCProviderMetadata metadata;
/** Constructor. */
public OIDCTokenConsumerFlowTest() {
super(TestConstants.FLOW_ID);
}
- /** Pre-test work. */
+ /**
+ * Pre-test work.
+ *
+ * @throws Exception on error
+ */
@BeforeMethod
- public void beforeMethod() {
+ public void beforeMethod() throws Exception{
setDefaultAuth();
final ApplicationContext applicationContext2 = applicationContext;
if (applicationContext2 != null) {
@@ -144,6 +154,10 @@ public class OIDCTokenConsumerFlowTest extends AbstractSPFlowTest {
if (httpClient == null) {
fail("Mocked Http Client could not be found");
}
+ // Add a default metadata response
+ final var metadataFromFile = new ClassPathResource("metadata/openid-configuration.json");
+ final String json = new String(metadataFromFile.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
+ metadata = OIDCProviderMetadata.parse(JSONObjectUtils.parse(json));
}
@@ -704,6 +718,13 @@ public class OIDCTokenConsumerFlowTest extends AbstractSPFlowTest {
private void mockOIDCEndpoints(final OIDCTokenResponse tokenResponse,
final UserInfoSuccessResponse userInfoResponse) throws IOException {
+ Mockito.when(httpClient.execute(
+ Mockito.argThat(req -> req != null && req.getRequestUri().toString()
+ .contains(".well-known/openid-configuration")),
+ Mockito.any(HttpContext.class),
+ Mockito.any(HttpClientResponseHandler.class)))
+ .thenReturn(metadata);
+
Mockito.when(httpClient.execute(
Mockito.argThat(req -> req != null && req.getRequestUri().toString().contains("/token")),
Mockito.any(HttpContext.class),
diff --git a/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/oidc-metadata-providers.xml b/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/oidc-metadata-providers.xml
new file mode 100644
index 0000000..fb883bc
--- /dev/null
+++ b/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/oidc-metadata-providers.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:c="http://www.springframework.org/schema/c" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+
+ default-init-method="initialize" default-destroy-method="destroy">
+
+ <!--
+ The default metadata provider fetches OpenID Provider configuration metadata from the issuers well-known
+ location.
+ -->
+ <util:list id="shibboleth.sp.ProviderMetadataResolvers">
+ <ref bean="ProviderHTTPResolver" />
+ </util:list>
+
+ <bean id="ProviderHTTPResolver" parent="shibboleth.sp.OIDCProviderMetadataResolver">
+ <constructor-arg>
+ <bean parent="shibboleth.sp.CacheBuilder">
+ <constructor-arg>
+ <bean p:cacheId="ProviderHTTPDynamicResolver"
+ parent="shibboleth.sp.BaseProviderDynamicCacheBuilderSpec"
+ p:minCacheDuration="PT5S"
+ p:maxCacheDuration="PT10S"
+ p:cleanupTaskInterval="PT30M"/>
+ </constructor-arg>
+ </bean>
+ </constructor-arg>
+ </bean>
+
+</beans>
\ No newline at end of file
diff --git a/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/oidc-test-agents.xml b/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/oidc-test-agents.xml
index d6e7c7b..e227f93 100644
--- a/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/oidc-test-agents.xml
+++ b/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/oidc-test-agents.xml
@@ -22,20 +22,16 @@
p:issuer="testsp.example.org">
<property name="applications">
<set>
- <bean p:id="test-oidc-application-with-default-profile" parent="shibboleth.sp.Application"
- p:metadataResolver-ref="shibboleth.ProviderMetadataResolverService"/>
+ <bean p:id="test-oidc-application-with-default-profile" parent="shibboleth.sp.Application"/>
<bean p:id="test-oidc-application-without-ro" parent="shibboleth.sp.Application"
- p:profileConfigurations-ref="test.ProfileConfigurations"
- p:metadataResolver-ref="shibboleth.ProviderMetadataResolverService"/>
+ p:profileConfigurations-ref="test.ProfileConfigurations"/>
<bean p:id="test-oidc-application-with-ro" parent="shibboleth.sp.Application"
- p:profileConfigurations-ref="test.RequestObjectProfileConfigurations"
- p:metadataResolver-ref="shibboleth.ProviderMetadataResolverService"/>
+ p:profileConfigurations-ref="test.RequestObjectProfileConfigurations"/>
<bean p:id="test-oidc-application-with-ro-with-requested-attrs" parent="shibboleth.sp.Application"
- p:profileConfigurations-ref="test.RequestedClaimsProfileConfigurations"
- p:metadataResolver-ref="shibboleth.ProviderMetadataResolverService"/>
+ p:profileConfigurations-ref="test.RequestedClaimsProfileConfigurations"/>
</set>
</property>
</bean>
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/metadata/impl/ApplicationMetadataResolverLookupFunction.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ApplicationMetadataResolverLookupFunction.java
similarity index 52%
rename from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/metadata/impl/ApplicationMetadataResolverLookupFunction.java
rename to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ApplicationMetadataResolverLookupFunction.java
index bf164fa..58512fd 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/metadata/impl/ApplicationMetadataResolverLookupFunction.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ApplicationMetadataResolverLookupFunction.java
@@ -12,31 +12,25 @@
* limitations under the License.
*/
-package net.shibboleth.sp.oidc.metadata.impl;
-
-import java.io.IOException;
+package net.shibboleth.sp.oidc.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.slf4j.Logger;
-import org.springframework.core.io.ClassPathResource;
import net.shibboleth.oidc.metadata.ProviderMetadataResolver;
-import net.shibboleth.oidc.metadata.impl.FilesystemProviderMetadataResolver;
+import net.shibboleth.oidc.metadata.impl.ReloadingProviderMetadataProvider;
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.oidc.OIDCProtocolSupportService;
import net.shibboleth.sp.profile.context.navigate.messaging.AbstractAgentRequestLookupFunction;
/**
- * Locates the {@link MetadataResolver} associated with the {@link Application} making an agent request,
- * and wraps it in a {@link ProviderMetadataResolver}.
- *
- * TODO I think this will eventually exist in the SP core and be more generic.
+ * Locates the {@link ProviderMetadataResolver} associated with the {@link Application} making an agent request.
*/
public class ApplicationMetadataResolverLookupFunction
extends AbstractAgentRequestLookupFunction<ProviderMetadataResolver> {
@@ -51,29 +45,26 @@ public class ApplicationMetadataResolverLookupFunction
final Application application = arc.getApplication();
if (application != null) {
try {
-// final ReloadingProviderMetadataProvider metadataResolver =
-// new ReloadingProviderMetadataProvider(application.getMetadataResolver());
-// metadataResolver.setId(application.getId() + " MetadataResolver");
-// metadataResolver.initialize();
-//
-// final ProviderMetadataResolver roleResolver =
-// new ProviderMetadataResolver(metadataResolver);
-// roleResolver.initialize();
-
- // FIXME, this will need changing over once supported to take from Application
- final FilesystemProviderMetadataResolver fsr =
- new FilesystemProviderMetadataResolver(
- new ClassPathResource("metadata/openid-configuration.json"));
- fsr.setId(application.getId() + " MetadataResolver");
- fsr.initialize();
+ final OIDCProtocolSupportService supportService =
+ application.getProtocolSupportService(OIDCProtocolSupportService.PROTOCOL_ID,
+ OIDCProtocolSupportService.class);
- return fsr;
- } catch (final IOException | ComponentInitializationException e) {
- log.error("Exception wrapping Application-supplied MetadataResolver for use", e);
+ if (supportService != null) {
+ final ReloadingProviderMetadataProvider metadataResolver =
+ new ReloadingProviderMetadataProvider(supportService.getMetadataResolver());
+ metadataResolver.setId(application.getId() + " MetadataResolver");
+ metadataResolver.initialize();
+ return metadataResolver;
+ } else {
+ log.warn("Application did not supply an OIDC ProtocolSupportService instance");
+ }
+ } catch (final ComponentInitializationException e) {
+ log.error("Exception wrapping Application-supplied ProviderMetadataResolver for use", e);
}
+ } else {
+ log.warn("Application was not available to acquire necessary services");
}
- }
-
+ }
return null;
}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ExtractOIDCClaims.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ExtractOIDCClaims.java
index ff33cab..dd5ae6d 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ExtractOIDCClaims.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ExtractOIDCClaims.java
@@ -28,7 +28,6 @@ import org.opensaml.messaging.context.navigate.RecursiveTypedParentContextLookup
import org.opensaml.profile.action.ActionSupport;
import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.saml.metadata.resolver.MetadataResolver;
import org.slf4j.Logger;
import com.google.common.collect.HashMultimap;
@@ -53,6 +52,7 @@ import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
import net.shibboleth.idp.attribute.transcoding.TranscoderSupport;
import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
import net.shibboleth.idp.profile.IdPEventIds;
+import net.shibboleth.oidc.metadata.ProviderMetadataResolver;
import net.shibboleth.oidc.profile.config.OIDCSSORelyingPartyConfiguration;
import net.shibboleth.oidc.profile.context.EndUserClaimsContext;
import net.shibboleth.profile.context.RelyingPartyContext;
@@ -68,6 +68,7 @@ import net.shibboleth.shared.primitive.LoggerFactory;
import net.shibboleth.shared.service.ServiceException;
import net.shibboleth.shared.service.ServiceableComponent;
import net.shibboleth.sp.Application;
+import net.shibboleth.sp.oidc.OIDCProtocolSupportService;
import net.shibboleth.sp.profile.AbstractApplicationAction;
/**
@@ -376,15 +377,26 @@ public class ExtractOIDCClaims extends AbstractApplicationAction {
populateFilterContext(profileRequestContext, filterContext);
try (final ServiceableComponent<AttributeFilter> filterComponent =
- ensureApplication().getAttributeFilter().getServiceableComponent();
- final ServiceableComponent<MetadataResolver> metadataResolverComponent =
- ensureApplication().getMetadataResolver().getServiceableComponent()) {
+ ensureApplication().getAttributeFilter().getServiceableComponent()) {
- // TODO, can only use SAML metadata here. Populate here for locking scope.
- //filterContext.setMetadataResolver(metadataResolverComponent.getComponent());
+ final OIDCProtocolSupportService supportService =
+ ensureApplication().getProtocolSupportService(OIDCProtocolSupportService.PROTOCOL_ID,
+ OIDCProtocolSupportService.class);
- final AttributeFilter filter = filterComponent.getComponent();
- filter.filterAttributes(filterContext);
+ if (supportService != null) {
+ try (final ServiceableComponent<ProviderMetadataResolver> metadataComponent =
+ supportService.getMetadataResolver().getServiceableComponent()) {
+ // TODO, can only use SAML metadata here. Populate here for locking scope.
+ //filterContext.setMetadataResolver(metadataResolverComponent.getComponent());
+ final AttributeFilter filter = filterComponent.getComponent();
+ filter.filterAttributes(filterContext);
+ } catch (final ServiceException e) {
+ log.error("{} Invalid ProviderMetadataResolver configuration", getLogPrefix(), e);
+ }
+ } else {
+ 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