[java-idp-plugin-oidc-op-oidfed] 02/03: Harmonise the merging of local metadata policy to use the same logic as with federation policies

Codeberg noreply at shibboleth.net
Sun Oct 11 15:22:37 UTC 2026


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/2a16c1a9dfe87efeed1fac7c93fbe443740ad855

commit 2a16c1a9dfe87efeed1fac7c93fbe443740ad855
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Sun Oct 11 18:20:46 2026 +0300

    Harmonise the merging of local metadata policy to use the same logic as with federation policies
    
    - Exploit the existing default arraysAsSpaceSeparatedList (scope)
---
 .../DefaultLocalMetadataPolicyMergingStrategy.java | 63 ++++++++++++++++++----
 .../oidfed/metadata-lookup-ext-oidfed-beans.xml    |  3 +-
 .../idp/flows/oidfed/register/register-beans.xml   |  3 +-
 .../idp/service/relying-party/postconfig.xml       |  8 ++-
 4 files changed, 64 insertions(+), 13 deletions(-)

diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/navigate/DefaultLocalMetadataPolicyMergingStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/navigate/DefaultLocalMetadataPolicyMergingStrategy.java
index 14eeb8f..5c647bc 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/navigate/DefaultLocalMetadataPolicyMergingStrategy.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/navigate/DefaultLocalMetadataPolicyMergingStrategy.java
@@ -14,7 +14,9 @@
 
 package net.shibboleth.idp.plugin.oidc.op.oidfed.profile.navigate;
 
+import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.function.BiFunction;
 
 import javax.annotation.Nonnull;
@@ -27,11 +29,14 @@ import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
 
 import net.minidev.json.JSONObject;
 import net.shibboleth.oidc.metadata.policy.MetadataPolicy;
+import net.shibboleth.oidfed.metadata.policy.FederationMetadataPolicyHelper;
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.collection.Pair;
 import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.logic.ConstraintViolationException;
 import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
@@ -47,6 +52,16 @@ public class DefaultLocalMetadataPolicyMergingStrategy extends AbstractIdentifia
     /** Enforcer function for applying metadata policy for an item. */
     @NonnullAfterInit private BiFunction<Object, MetadataPolicy, Pair<Object, Boolean>> metadataPolicyEnforcer;
 
+    /** List of claim names who are transformed from a space-separated String into a List. */
+    @Nonnull private List<String> arraysAsSpaceSeparatedList;
+
+    /**
+     * Constructor.
+     */
+    public DefaultLocalMetadataPolicyMergingStrategy() {
+        arraysAsSpaceSeparatedList = CollectionSupport.listOf("scope");
+    }
+
     /**
      * Set the enforcer function for applying metadata policy for an item.
      * 
@@ -58,6 +73,16 @@ public class DefaultLocalMetadataPolicyMergingStrategy extends AbstractIdentifia
         metadataPolicyEnforcer = Constraint.isNotNull(enforcer, "Metadata policy enforcer cannot be null");
     }
 
+    /**
+     * Set the list of claim names who are transformed from a space-separated String into a List.
+     * 
+     * @param list list of claim names
+     */
+    public void setArraysAsSpaceSeparatedList(@Nonnull final List<String> list) {
+        checkSetterPreconditions();
+        arraysAsSpaceSeparatedList = Constraint.isNotNull(list, "ArraysAsSpaceSeparatedList cannot be null");
+    }
+
     /** {@inheritDoc} */
     @Override
     protected void doInitialize() throws ComponentInitializationException {
@@ -82,18 +107,36 @@ public class DefaultLocalMetadataPolicyMergingStrategy extends AbstractIdentifia
         final JSONObject result = inputMetadata.toJSONObject();
         boolean compliant = true;
         for (final String claim : localPolicy.keySet()) {
+            assert claim != null;
             final MetadataPolicy policy = localPolicy.get(claim);
             final Object value = inputMetadata.getOIDCMetadata().toJSONObject().get(claim);
-            log.debug("Claim {} set in policy included in the input: {}", claim, value == null);
-            final Pair<Object,Boolean> mergeResult = metadataPolicyEnforcer.apply(value, policy);
-            final Boolean enforcerResult = mergeResult != null ? mergeResult.getSecond() : null;
-            if (enforcerResult == null || !enforcerResult.booleanValue()) {
-                log.warn("Metadata claim {} is not compliant with the policy", claim);
-                compliant = false;
-            } else {
-                log.trace("Validation result is OK for claim {}", claim);
-                final Object enforcedValue = mergeResult != null ? mergeResult.getFirst() : null;
-                result.put(claim, enforcedValue);
+            try {
+                final Object enforcerInput = FederationMetadataPolicyHelper.transformSpaceSeparatedStringIntoList(
+                        arraysAsSpaceSeparatedList, claim, value);
+
+                log.debug("Claim {} set in policy included in the input: {}", claim, value == null);
+                final Pair<Object,Boolean> mergeResult = metadataPolicyEnforcer.apply(enforcerInput, policy);
+                final Boolean enforcerResult = mergeResult != null ? mergeResult.getSecond() : null;
+                if (enforcerResult == null || !enforcerResult.booleanValue()) {
+                    log.warn("Metadata claim {} is not compliant with the policy", claim);
+                    compliant = false;
+                } else {
+                    final Object enforcedValue = Optional.ofNullable(mergeResult)
+                            .map(pair -> pair.getFirst())
+                            .map(enforced -> FederationMetadataPolicyHelper.transformListIntoSpaceSeparatedString(
+                                    arraysAsSpaceSeparatedList, claim, enforced))
+                            .orElse(null);
+                    if (enforcedValue == null) {
+                        log.trace("Enforced value for claim {} is null, removing it from the result", claim);
+                        result.remove(claim);
+                    } else {
+                        log.trace("Enforced value for claim {}: {}", claim, enforcedValue);
+                        result.put(claim, enforcedValue);
+                    }
+                }
+            } catch (final ConstraintViolationException e) {
+                log.error("Could not apply the local metadata policy into the input metadata for claim {}", claim, e);
+                return null;
             }
         }
 
diff --git a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-beans.xml b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-beans.xml
index cc1b844..b1867e6 100644
--- a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-beans.xml
+++ b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-beans.xml
@@ -268,7 +268,8 @@
         </property>
         <property name="localMetadataPolicyMergingStrategy">
             <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.profile.navigate.DefaultLocalMetadataPolicyMergingStrategy"
-                p:metadataPolicyEnforcer="#{getObject('shibboleth.oidfed.trust-chain-resolver.MetadataPolicyEnforcer') ?: getObject('FlowDefaultMetadataPolicyEnforcer') ?: getObject('shibboleth.oidfed.trust-chain-resolver.DefaultMetadataPolicyEnforcer')}"/>
+                p:metadataPolicyEnforcer="#{getObject('shibboleth.oidfed.trust-chain-resolver.MetadataPolicyEnforcer') ?: getObject('FlowDefaultMetadataPolicyEnforcer') ?: getObject('shibboleth.oidfed.trust-chain-resolver.DefaultMetadataPolicyEnforcer')}"
+                p:arraysAsSpaceSeparatedList="#{getObject('shibboleth.oidfed.trust-chain-resolver.ArrayAsSpaceSeparatedList') ?: getObject('shibboleth.oidfed.trust-chain-resolver.DefaultArrayAsSpaceSeparatedList')}"/>
         </property>
         <property name="mandatoryTrustMarksLookupStrategy">
             <bean class="net.shibboleth.oidfed.profile.config.navigate.MandatoryTrustMarksLookupFunction"
diff --git a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/register/register-beans.xml b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/register/register-beans.xml
index 7de0a27..a2a48f1 100644
--- a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/register/register-beans.xml
+++ b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/register/register-beans.xml
@@ -401,7 +401,8 @@
         scope="prototype">
         <property name="localMetadataPolicyMergingStrategy">
             <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.profile.navigate.DefaultLocalMetadataPolicyMergingStrategy"
-                p:metadataPolicyEnforcer="#{getObject('shibboleth.oidfed.trust-chain-resolver.MetadataPolicyEnforcer') ?: getObject('FlowDefaultMetadataPolicyEnforcer') ?: getObject('shibboleth.oidfed.trust-chain-resolver.DefaultMetadataPolicyEnforcer')}"/>
+                p:metadataPolicyEnforcer="#{getObject('shibboleth.oidfed.trust-chain-resolver.MetadataPolicyEnforcer') ?: getObject('FlowDefaultMetadataPolicyEnforcer') ?: getObject('shibboleth.oidfed.trust-chain-resolver.DefaultMetadataPolicyEnforcer')}"
+                p:arraysAsSpaceSeparatedList="#{getObject('shibboleth.oidfed.trust-chain-resolver.ArrayAsSpaceSeparatedList') ?: getObject('shibboleth.oidfed.trust-chain-resolver.DefaultArrayAsSpaceSeparatedList')}"/>
         </property>
         <property name="mandatoryTrustMarksLookupStrategy">
             <bean class="net.shibboleth.oidfed.profile.config.navigate.MandatoryTrustMarksLookupFunction"
diff --git a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
index 3331822..9cfbdf9 100644
--- a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
+++ b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
@@ -30,7 +30,13 @@
                 <constructor-arg name="target">
                     <util:map>
                         <entry key="scope">
-                            <bean class="net.shibboleth.oidc.metadata.policy.MetadataPolicy" p:defaultValue="openid" />
+                            <bean class="net.shibboleth.oidc.metadata.policy.MetadataPolicy">
+                                <property name="defaultValue">
+                                    <util:list value-type="java.lang.String">
+                                        <value>openid</value>
+                                    </util:list>
+                                </property>
+                            </bean>
                         </entry>
                         <entry key="token_endpoint_auth_method">
                             <bean class="net.shibboleth.oidc.metadata.policy.MetadataPolicy" p:defaultValue="private_key_jwt" />

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


More information about the commits mailing list