[java-idp-oidc] 01/03: JOIDC-222 - Support for OpenID Federation

Henri Mikkonen henri.mikkonen at iki.fi
Fri May 2 12:01:59 UTC 2025


This is an automated email from the git hooks/post-receive script.

hjmikkon pushed a commit to branch dev/JOIDC-222
in repository java-idp-oidc.

View the commit online:
http://git.shibboleth.net/view/?p=java-idp-oidc.git;a=commit;h=f03f8ef2ce41e159f6331fe51e9b3b16aea73a14

commit f03f8ef2ce41e159f6331fe51e9b3b16aea73a14
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Fri May 2 10:35:21 2025 +0300

    JOIDC-222 - Support for OpenID Federation
    
    https://shibboleth.atlassian.net/browse/JOIDC-222
    
    Some fixes for th eexplicit registration implementation
    - The URL advertised in the entity configuration is ../oidfed/register and not ../oidfed/registration
    - Fixed wiring of the issuer-claim
      - The profile configuration now implements OverriddenIssuerProfileConfiguration
    - Fixed wiring of the subject-claim
      - shibboleth.ClientIDLookupStrategy is exploited for fetching the RP's federation entity ID
---
 ...onExplicitRegistrationProfileConfiguration.java | 28 ++++++++++++++++++++++
 ...onExplicitRegistrationProfileConfiguration.java |  3 ++-
 .../META-INF/net.shibboleth.idp/postconfig.xml     |  2 +-
 .../idp/flows/oidfed/register/register-beans.xml   |  7 +++++-
 .../idp/service/relying-party/postconfig.xml       |  1 +
 .../flow/oidfed/EntityConfigurationFlowTest.java   |  2 +-
 .../profile/flow/oidfed/RegistrationFlowTest.java  |  3 +++
 7 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/DefaultOIDFederationExplicitRegistrationProfileConfiguration.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/DefaultOIDFederationExplicitRegistrationProfileConfiguration.java
index 2f5f1bd4..5001bc59 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/DefaultOIDFederationExplicitRegistrationProfileConfiguration.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/DefaultOIDFederationExplicitRegistrationProfileConfiguration.java
@@ -49,6 +49,9 @@ public class DefaultOIDFederationExplicitRegistrationProfileConfiguration
     @Nonnull @NotEmpty
     public static final String PROFILE_COUNTER = "net.shibboleth.idp.profiles.oidfed.explicitregistration";
 
+    /** Lookup function to override issuer value. */
+    @Nonnull private Function<ProfileRequestContext,String> issuerLookupStrategy;
+
     /** Predicate used to indicate whether authorization code flow is supported by this profile. Default true. */
     @Nonnull private Predicate<ProfileRequestContext> authorizationCodeFlowPredicate;
 
@@ -80,6 +83,7 @@ public class DefaultOIDFederationExplicitRegistrationProfileConfiguration
      */
     public DefaultOIDFederationExplicitRegistrationProfileConfiguration(@Nonnull @NotEmpty final String profileId) {
         super(profileId);
+        issuerLookupStrategy = FunctionSupport.constant(null);
         authorizationCodeFlowPredicate = PredicateSupport.alwaysTrue();
         implicitFlowPredicate = PredicateSupport.alwaysTrue();
         refreshTokensPredicate = PredicateSupport.alwaysTrue();
@@ -92,6 +96,30 @@ public class DefaultOIDFederationExplicitRegistrationProfileConfiguration
         entityStatementClaimsSetManipulationStrategyLookupStrategy = FunctionSupport.constant(null);
     }
 
+    /** {@inheritDoc} */
+    @Override
+    @Nullable @NotEmpty public String getIssuer(@Nullable final ProfileRequestContext profileRequestContext) {
+        return issuerLookupStrategy.apply(profileRequestContext);
+    }
+
+    /**
+     * Set overridden issuer value.
+     * 
+     * @param issuer issuer value
+     */
+    public void setIssuer(@Nullable @NotEmpty final String issuer) {
+        issuerLookupStrategy = FunctionSupport.constant(issuer);
+    }
+
+    /**
+     * Sets lookup strategy for overridden issuer value.
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setIssuerLookupStrategy(@Nonnull final Function<ProfileRequestContext,String> strategy) {
+        issuerLookupStrategy = Constraint.isNotNull(strategy, "Issuer lookup strategy cannot be null");
+    }
+
     /** {@inheritDoc} */
     @Override
     public boolean isAuthorizationCodeFlowEnabled(@Nullable final ProfileRequestContext profileRequestContext) {
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/OIDFederationExplicitRegistrationProfileConfiguration.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/OIDFederationExplicitRegistrationProfileConfiguration.java
index 7e0e94d9..97a72927 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/OIDFederationExplicitRegistrationProfileConfiguration.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/OIDFederationExplicitRegistrationProfileConfiguration.java
@@ -22,6 +22,7 @@ import javax.annotation.Nullable;
 import org.opensaml.profile.context.ProfileRequestContext;
 
 import net.shibboleth.oidc.profile.oauth2.config.OAuth2FlowAwareProfileConfiguration;
+import net.shibboleth.profile.config.OverriddenIssuerProfileConfiguration;
 import net.shibboleth.shared.annotation.ConfigurationSetting;
 import net.shibboleth.shared.annotation.constraint.NonnullElements;
 import net.shibboleth.shared.annotation.constraint.NotLive;
@@ -32,7 +33,7 @@ import net.shibboleth.shared.annotation.constraint.Unmodifiable;
  */
 public interface OIDFederationExplicitRegistrationProfileConfiguration
     extends OIDFederationRegistrationProfileConfiguration, OAuth2FlowAwareProfileConfiguration,
-        OIDFederationEntityStatementProducingProfileConfiguration {
+        OIDFederationEntityStatementProducingProfileConfiguration, OverriddenIssuerProfileConfiguration {
 
     /** ID for this profile configuration. */
     public static final String PROFILE_ID = "http://shibboleth.net/ns/profiles/oidfed/explicitregistration";
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
index c9fa7e22..add39a80 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
@@ -931,7 +931,7 @@
         class="net.shibboleth.idp.plugin.oidc.op.metadata.impl.FunctionMetadataValueResolver">
         <property name="resolverFunction">
             <bean parent="shibboleth.Functions.Expression"
-                c:expression="#custom.get().getRequestURL().toString().replace('/profile/oidfed/entity-configuration','/profile/oidfed/registration').replace('/.well-known/openid-federation','/profile/oidfed/registration')"
+                c:expression="#custom.get().getRequestURL().toString().replace('/profile/oidfed/entity-configuration','/profile/oidfed/register').replace('/.well-known/openid-federation','/profile/oidfed/register')"
                 p:customObject-ref="shibboleth.HttpServletRequestSupplier" />
         </property>
     </bean>
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/register/register-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/register/register-beans.xml
index 3cb3d50c..6ba028da 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/register/register-beans.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/register/register-beans.xml
@@ -280,7 +280,12 @@
     <bean id="BuildEntityStatement"
         class="net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl.BuildExplicitRegistrationResponse" scope="prototype"
         p:identifierGeneratorLookupStrategy-ref="shibboleth.oidc.DefaultIdentifierGenerationStrategy"
-        p:objectMapper-ref="#{'%{idp.oidc.logging.objectMapper:shibboleth.oidc.JSONObjectMapper}'.trim()}" />
+        p:objectMapper-ref="#{'%{idp.oidc.logging.objectMapper:shibboleth.oidc.JSONObjectMapper}'.trim()}">
+        <property name="subjectLookupStrategy">
+            <bean parent="shibboleth.Functions.Expression" p:customObject-ref="shibboleth.ClientIDLookupStrategy"
+                c:expression="#custom.apply(#input.ensureInboundMessageContext()).getValue()" />
+        </property>
+    </bean>
 
     <bean id="SignEntityStatement" class="net.shibboleth.idp.profile.impl.WebFlowMessageHandlerAdaptor"
             scope="prototype" c:executionDirection="OUTBOUND ">
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
index 3c10ef46..0ad6fc14 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
@@ -120,6 +120,7 @@
 
     <bean id="OIDFED.ExplicitRegistration" parent="AbstractOIDFederationProfile" lazy-init="true"
         class="net.shibboleth.idp.plugin.oidc.op.oidfed.config.DefaultOIDFederationExplicitRegistrationProfileConfiguration"
+        p:issuer-ref="shibboleth.oidc.issuer"
         p:mandatoryTrustMarks="%{idp.oidfed.explicitRegistration.mandatoryTrustMarks:}" />
 
     <bean id="OIDFED.ResolveEntity" parent="AbstractOIDFederationProfile" lazy-init="true"
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/EntityConfigurationFlowTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/EntityConfigurationFlowTest.java
index 5f44f39b..1ddd2cd2 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/EntityConfigurationFlowTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/EntityConfigurationFlowTest.java
@@ -95,7 +95,7 @@ public class EntityConfigurationFlowTest extends AbstractFederationFlowTest {
                 List.of(ClientRegistrationType.AUTOMATIC, ClientRegistrationType.EXPLICIT)));
         try {
             Assert.assertEquals(metadata.getFederationRegistrationEndpointURI(),
-                    new URI("http://localhost/idp/profile/oidfed/registration"));
+                    new URI("http://localhost/idp/profile/oidfed/register"));
         } catch (URISyntaxException e) {
             Assert.fail("Could not build URI", e);
         }
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/RegistrationFlowTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/RegistrationFlowTest.java
index e048dabf..c532a0a7 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/RegistrationFlowTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/RegistrationFlowTest.java
@@ -120,6 +120,8 @@ public class RegistrationFlowTest extends AbstractFederationFlowTest {
             final String expectedClientId) throws IOException, ParseException, net.minidev.json.parser.ParseException {
         final EntityStatement entityStatement = response.getEntityStatement();
         final EntityStatementClaimsSet statementClaims = entityStatement.getClaimsSet();
+        Assert.assertNotNull(statementClaims.getIssuer());
+        Assert.assertEquals(statementClaims.getIssuer().getValue(), issuer);
         Assert.assertEquals(statementClaims.getAuthorityHints().stream().map(id -> id.getValue()).toList(),
                 List.of(anchorId));
         Assert.assertEquals(statementClaims.getClaim("trust_anchor"), anchorId);
@@ -128,6 +130,7 @@ public class RegistrationFlowTest extends AbstractFederationFlowTest {
         final String providedClientId = clientInfo.getID().getValue();
         assert providedClientId != null;
         Assert.assertEquals(providedClientId, expectedClientId);
+        Assert.assertEquals(entityStatement.getClaimsSet().getSubject().getValue(), expectedClientId);
         assert storageService != null;
         final StorageRecord<String> storageRecord =
                 storageService.read(BaseStorageServiceClientInformationComponent.CONTEXT_NAME, providedClientId);

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


More information about the commits mailing list