[java-idp-plugin-oidc-op-oidfed] 01/02: Fixed the wiring of authority_hints: it should only be included in the entity configuration

Codeberg noreply at shibboleth.net
Fri Nov 28 07:24:31 UTC 2025


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

codeberg pushed a commit to branch main
in repository java-idp-plugin-oidc-op-oidfed.

View the commit online:
https://codeberg.org/Shibboleth/java-idp-plugin-oidc-op-oidfed/commit/3a5ef4b4b1c3c2016052f12d8c5d3feea1751b4e

commit 3a5ef4b4b1c3c2016052f12d8c5d3feea1751b4e
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Fri Nov 28 07:58:16 2025 +0200

    Fixed the wiring of authority_hints: it should only be included in the entity configuration
    
    - Explicit registration response uses it for the immediate superior
    - Improved tests
---
 .../impl/AbstractBuildEntityStatementAction.java   | 10 +------
 .../profile/impl/BuildEntityConfiguration.java     | 35 +++++++++++++++++++++-
 .../flow/oidfed/EntityConfigurationFlowTest.java   |  3 ++
 .../profile/flow/oidfed/RegistrationFlowTest.java  |  2 ++
 .../profile/flow/oidfed/ResolveEntityFlowTest.java |  2 ++
 .../net/shibboleth/idp/module/conf/idp.properties  |  3 +-
 .../idp/module/conf/oidfed/oidfed.properties       |  1 +
 7 files changed, 45 insertions(+), 11 deletions(-)

diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/AbstractBuildEntityStatementAction.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/AbstractBuildEntityStatementAction.java
index 761baf9..e77eb2a 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/AbstractBuildEntityStatementAction.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/AbstractBuildEntityStatementAction.java
@@ -17,7 +17,6 @@ package net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl;
 import java.text.ParseException;
 import java.time.Instant;
 import java.util.Date;
-import java.util.List;
 import java.util.Map;
 import java.util.function.BiFunction;
 import java.util.function.Function;
@@ -40,7 +39,6 @@ import com.nimbusds.jwt.JWTClaimsSet;
 import com.nimbusds.jwt.PlainJWT;
 import com.nimbusds.openid.connect.sdk.federation.entities.EntityStatement;
 
-import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.config.navigate.AuthorityHintsLookupFunction;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.config.navigate.EntityStatementClaimsSetManipulationStrategyLookupFunction;
 import net.shibboleth.idp.profile.AbstractProfileAction;
 import net.shibboleth.idp.profile.IdPEventIds;
@@ -78,9 +76,6 @@ public abstract class AbstractBuildEntityStatementAction extends AbstractProfile
     /** Strategy used to locate the subcontext to hold the statement. */
     @Nonnull private Function<ProfileRequestContext,EntityStatementContext> entityStatementContextLookupStrategy;
 
-    /** Strategy used to locate authority hints. */
-    @Nonnull private Function<ProfileRequestContext,List<String>> authorityHintsLookupStrategy;
-
     /** Lookup function to supply strategy bi-function for manipulating entity statement claims set. */ 
     @Nonnull
     private Function<ProfileRequestContext,BiFunction<ProfileRequestContext,Map<String,Object>,Map<String,Object>>>
@@ -111,8 +106,6 @@ public abstract class AbstractBuildEntityStatementAction extends AbstractProfile
         assert escls != null;
         entityStatementContextLookupStrategy = escls; 
 
-        authorityHintsLookupStrategy = new AuthorityHintsLookupFunction();
-
         entityStatementClaimsSetManipulationStrategyLookupStrategy =
                 new EntityStatementClaimsSetManipulationStrategyLookupFunction();
     }
@@ -238,8 +231,7 @@ public abstract class AbstractBuildEntityStatementAction extends AbstractProfile
         final JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder()
                 .issuer(issuer)
                 .subject(subject)
-                .issueTime(Date.from(now))
-                .claim("authority_hints", authorityHintsLookupStrategy.apply(profileRequestContext));
+                .issueTime(Date.from(now));
         assert builder != null;
         if (!populateClaimsSetBuilder(builder, profileRequestContext)) {
             return;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/BuildEntityConfiguration.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/BuildEntityConfiguration.java
index 7ac31f7..2e1d935 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/BuildEntityConfiguration.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/BuildEntityConfiguration.java
@@ -33,6 +33,7 @@ import com.nimbusds.jose.jwk.JWK;
 import com.nimbusds.jose.jwk.JWKSet;
 import com.nimbusds.jwt.JWTClaimsSet;
 
+import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.config.navigate.AuthorityHintsLookupFunction;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.config.navigate.EntityStatementLifetimeLookupFunction;
 import net.shibboleth.idp.profile.IdPEventIds;
 import net.shibboleth.oidc.profile.config.navigate.JWTSignatureSigningConfigurationLookupFunction;
@@ -65,6 +66,9 @@ public class BuildEntityConfiguration extends AbstractBuildEntityStatementAction
     /** Strategy used to obtain the entity statement lifetime. */
     @Nonnull private Function<ProfileRequestContext,Duration> entityConfigurationLifetimeLookupStrategy;
 
+    /** Strategy used to locate authority hints. */
+    @Nonnull private Function<ProfileRequestContext,List<String>> authorityHintsLookupStrategy;
+
     /** Metadata to publish. */
     @NonnullBeforeExec private Map<String,Map<String,Object>> metadata;
 
@@ -72,6 +76,20 @@ public class BuildEntityConfiguration extends AbstractBuildEntityStatementAction
     public BuildEntityConfiguration() {
         signingConfigurationsLookupStrategy = new JWTSignatureSigningConfigurationLookupFunction();
         entityConfigurationLifetimeLookupStrategy = new EntityStatementLifetimeLookupFunction();
+        authorityHintsLookupStrategy = new AuthorityHintsLookupFunction();
+    }
+
+    /**
+     * Set the strategy used to locate the {@link SignatureSigningConfiguration}s to fetch JWK set from. 
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setSigningConfigurationsLookupStrategy(
+            @Nonnull final Function<ProfileRequestContext,List<SignatureSigningConfiguration>> strategy) {
+        checkSetterPreconditions();
+
+        signingConfigurationsLookupStrategy =
+                Constraint.isNotNull(strategy, "Signing configuration lookup strategy cannot be null");
     }
 
     /**
@@ -81,12 +99,23 @@ public class BuildEntityConfiguration extends AbstractBuildEntityStatementAction
      */
     public void setEntityConfigurationLifetimeLookupStrategy(
             @Nonnull final Function<ProfileRequestContext,Duration> strategy) {
-        ifInitializedThrowUnmodifiabledComponentException();
+        checkSetterPreconditions();
         
         entityConfigurationLifetimeLookupStrategy =
                 Constraint.isNotNull(strategy, "Entity configuration lifetime lookup strategy cannot be null");
     }
 
+    /**
+     * Set the strategy used to locate authority hints.
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setAuthorityHintsLookupStrategy(@Nonnull final Function<ProfileRequestContext,List<String>> strategy) {
+        checkSetterPreconditions();
+
+        authorityHintsLookupStrategy = Constraint.isNotNull(strategy, "Authority hints lookup strategy cannot be null");
+    }
+
     /** {@inheritDoc} */
     @Override
     protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
@@ -140,6 +169,10 @@ public class BuildEntityConfiguration extends AbstractBuildEntityStatementAction
         builder.expirationTime(Date.from(dateExp));
         builder.claim("jwks", new JWKSet(jwks).toJSONObject(true));
         builder.claim("metadata", CollectionSupport.copyToMap(metadata));
+        final List<String> authorityHints = authorityHintsLookupStrategy.apply(profileRequestContext);
+        if (authorityHints != null && !authorityHints.isEmpty()) {
+            builder.claim("authority_hints", authorityHints);
+        }
         return true;
    }
 
diff --git a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/EntityConfigurationFlowTest.java b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/EntityConfigurationFlowTest.java
index f079c81..0d718bc 100644
--- a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/EntityConfigurationFlowTest.java
+++ b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/EntityConfigurationFlowTest.java
@@ -30,6 +30,7 @@ import com.nimbusds.jose.Algorithm;
 import com.nimbusds.oauth2.sdk.ParseException;
 import com.nimbusds.oauth2.sdk.Response;
 import com.nimbusds.oauth2.sdk.id.Issuer;
+import com.nimbusds.openid.connect.sdk.federation.entities.EntityID;
 import com.nimbusds.openid.connect.sdk.federation.entities.EntityStatement;
 import com.nimbusds.openid.connect.sdk.federation.entities.FederationEntityMetadata;
 import com.nimbusds.openid.connect.sdk.federation.registration.ClientRegistrationType;
@@ -103,6 +104,8 @@ public class EntityConfigurationFlowTest extends AbstractFederationFlowTest {
         final FederationEntityMetadata entityMetadata = entityStatement.getClaimsSet().getFederationEntityMetadata();
         Assert.assertEquals(entityMetadata.getOrganizationName(), "Example organization");
         Assert.assertEquals(entityMetadata.getContacts(), List.of("contact at example.org"));
+        Assert.assertEquals(entityStatement.getClaimsSet().getAuthorityHints(),
+                List.of(new EntityID("https://anchor1.example.org"), new EntityID("https://anchor2.example.org")));
     }
 
     protected boolean containsAll(Collection<? extends Algorithm> algs, Collection<String> strings) {
diff --git a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/RegistrationFlowTest.java b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/RegistrationFlowTest.java
index 711c1e0..6200d8a 100644
--- a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/RegistrationFlowTest.java
+++ b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/RegistrationFlowTest.java
@@ -42,6 +42,7 @@ import com.nimbusds.jose.jwk.JWKSet;
 import com.nimbusds.jwt.SignedJWT;
 import com.nimbusds.oauth2.sdk.ParseException;
 import com.nimbusds.oauth2.sdk.Scope;
+import com.nimbusds.openid.connect.sdk.federation.entities.EntityID;
 import com.nimbusds.openid.connect.sdk.federation.entities.EntityStatement;
 import com.nimbusds.openid.connect.sdk.federation.entities.EntityStatementClaimsSet;
 import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
@@ -483,6 +484,7 @@ public class RegistrationFlowTest extends AbstractFederationFlowTest {
         Assert.assertEquals(storedInfo.getOIDCMetadata().getRedirectionURIStrings(),
                 metadata.getRedirectionURIStrings());
         Assert.assertTrue(metadata.getRedirectionURIStrings().contains(redirectUri));
+        Assert.assertEquals(entityStatement.getClaimsSet().getAuthorityHints(), List.of(new EntityID(anchorId)));
         return storedInfo;
     }
 
diff --git a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/ResolveEntityFlowTest.java b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/ResolveEntityFlowTest.java
index c2049c0..05f1322 100644
--- a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/ResolveEntityFlowTest.java
+++ b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/ResolveEntityFlowTest.java
@@ -79,6 +79,7 @@ public class ResolveEntityFlowTest extends AbstractFederationFlowTest {
         Assert.assertEquals(response.getHeader().getType(), new JOSEObjectType("resolve-response+jwt"));
         Assert.assertEquals(response.getJWTClaimsSet().getSubject(), clientId);
         Assert.assertNotNull(response.getJWTClaimsSet().getClaim("metadata"));
+        Assert.assertNull(response.getJWTClaimsSet().getClaim("authority_hints"));
     }
 
     @Test
@@ -115,6 +116,7 @@ public class ResolveEntityFlowTest extends AbstractFederationFlowTest {
         Assert.assertEquals(response.getHeader().getType(), new JOSEObjectType("resolve-response+jwt"));
         Assert.assertEquals(response.getJWTClaimsSet().getSubject(), entityId);
         Assert.assertNotNull(response.getJWTClaimsSet().getClaim("metadata"));
+        Assert.assertNull(response.getJWTClaimsSet().getClaim("authority_hints"));
     }
 
     @Test
diff --git a/idp-oidfed-op-impl/src/test/resources/net/shibboleth/idp/module/conf/idp.properties b/idp-oidfed-op-impl/src/test/resources/net/shibboleth/idp/module/conf/idp.properties
index d78cd53..07392d5 100644
--- a/idp-oidfed-op-impl/src/test/resources/net/shibboleth/idp/module/conf/idp.properties
+++ b/idp-oidfed-op-impl/src/test/resources/net/shibboleth/idp/module/conf/idp.properties
@@ -10,7 +10,8 @@ idp.additionalProperties = /conf/ldap.properties, \
     /conf/authn/authn.properties, \
     /conf/authn/duo.properties, \
     /conf/oidc.properties, \
-    /credentials/secrets.properties
+    /credentials/secrets.properties, \
+    /conf/oidfed/oidfed.properties
 
 # In most cases (and unless noted in the surrounding comments) the
 # commented settings in the distributed files are the default
diff --git a/idp-oidfed-op-impl/src/test/resources/net/shibboleth/idp/module/conf/oidfed/oidfed.properties b/idp-oidfed-op-impl/src/test/resources/net/shibboleth/idp/module/conf/oidfed/oidfed.properties
new file mode 100644
index 0000000..a844603
--- /dev/null
+++ b/idp-oidfed-op-impl/src/test/resources/net/shibboleth/idp/module/conf/oidfed/oidfed.properties
@@ -0,0 +1 @@
+idp.oidfed.entity.authorityHints = https://anchor1.example.org, https://anchor2.example.org
\ 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