[java-oidfed-common] 01/02: Refactor the trust mark validation logic when trust anchor is the issuer

Codeberg noreply at shibboleth.net
Wed Sep 16 09:21:00 UTC 2026


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

codeberg pushed a commit to branch main
in repository java-oidfed-common.

View the commit online:
https://codeberg.org/Shibboleth/java-oidfed-common/commit/b3c2e9dd9fec18543455f3496c897533c8f29b64

commit b3c2e9dd9fec18543455f3496c897533c8f29b64
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Wed Sep 16 12:14:45 2026 +0300

    Refactor the trust mark validation logic when trust anchor is the issuer
    
    - When no trust chain is available, require issuer entity configuration to be signed by a locally trusted key
---
 .../META-INF/net.shibboleth.idp/postconfig.xml     | 28 +++++++++++++++++--
 ...ustMarkValidationCriteriaSetLookupFunction.java | 31 +++++++++++++++-------
 2 files changed, 47 insertions(+), 12 deletions(-)

diff --git a/oidfed-common-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml b/oidfed-common-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
index 4000cd5..5a58927 100644
--- a/oidfed-common-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
+++ b/oidfed-common-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
@@ -591,7 +591,19 @@
                                 <bean class="net.shibboleth.oidfed.metadata.cache.trustmark.DefaultTrustMarkValidationCriteriaSetLookupFunction"
                                     p:trustChainCache-ref="shibboleth.oidfed.TrustChainMetadataCache"
                                     p:entityConfigurationCache-ref="shibboleth.oidfed.EntityConfigurationMetadataCache"
-                                    p:localTrustAnchorsCache-ref="shibboleth.oidfed.LocalTrustAnchorsMetadataCache"/>
+                                    p:localTrustAnchorsCache-ref="shibboleth.oidfed.LocalTrustAnchorsMetadataCache">
+                                    <property name="trustEngine">
+                                        <bean class="net.shibboleth.oidc.security.impl.ExplicitKeySignedJWTTrustEngine">
+                                            <constructor-arg index="0">
+                                                <bean class="net.shibboleth.oidfed.security.credential.DefaultLocalTrustAnchorCredentialResolver"
+                                                    c:cache-ref="shibboleth.oidfed.LocalTrustAnchorsMetadataCache" />
+                                            </constructor-arg>
+                                            <constructor-arg index="1">
+                                                <bean class="net.shibboleth.oidfed.security.credential.DefaultPayloadJOSEObjectCredentialResolver" />
+                                            </constructor-arg>
+                                        </bean>
+                                    </property>
+                                </bean>
                             </property>
                         </bean>
                         <bean class="net.shibboleth.oidfed.metadata.cache.DefaultEntityStatementContentValidationCondition"
@@ -695,7 +707,19 @@
                                 <bean class="net.shibboleth.oidfed.metadata.cache.trustmark.DefaultTrustMarkValidationCriteriaSetLookupFunction"
                                     p:trustChainCache-ref="shibboleth.oidfed.TrustChainMetadataCache"
                                     p:entityConfigurationCache-ref="shibboleth.oidfed.EntityConfigurationMetadataCache"
-                                    p:localTrustAnchorsCache-ref="shibboleth.oidfed.LocalTrustAnchorsMetadataCache"/>
+                                    p:localTrustAnchorsCache-ref="shibboleth.oidfed.LocalTrustAnchorsMetadataCache">
+                                    <property name="trustEngine">
+                                        <bean class="net.shibboleth.oidc.security.impl.ExplicitKeySignedJWTTrustEngine">
+                                            <constructor-arg index="0">
+                                                <bean class="net.shibboleth.oidfed.security.credential.DefaultLocalTrustAnchorCredentialResolver"
+                                                    c:cache-ref="shibboleth.oidfed.LocalTrustAnchorsMetadataCache" />
+                                            </constructor-arg>
+                                            <constructor-arg index="1">
+                                                <bean class="net.shibboleth.oidfed.security.credential.DefaultPayloadJOSEObjectCredentialResolver" />
+                                            </constructor-arg>
+                                        </bean>
+                                    </property>
+                                </bean>
                             </property>
                         </bean>
                         <bean class="net.shibboleth.oidfed.metadata.cache.DefaultEntityStatementContentValidationCondition"
diff --git a/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/cache/trustmark/DefaultTrustMarkValidationCriteriaSetLookupFunction.java b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/cache/trustmark/DefaultTrustMarkValidationCriteriaSetLookupFunction.java
index 7567bd5..1058e04 100644
--- a/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/cache/trustmark/DefaultTrustMarkValidationCriteriaSetLookupFunction.java
+++ b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/cache/trustmark/DefaultTrustMarkValidationCriteriaSetLookupFunction.java
@@ -28,16 +28,17 @@ import net.shibboleth.oidc.metadata.cache.MetadataCacheException;
 import net.shibboleth.oidfed.metadata.BaseJWTWrapper;
 import net.shibboleth.oidfed.metadata.EntityConfiguration;
 import net.shibboleth.oidfed.metadata.EntityStatement;
+import net.shibboleth.oidfed.metadata.cache.AbstractTrustEngineSignatureValidationComponent;
 import net.shibboleth.oidfed.metadata.cache.BaseExpirableStatementContainer;
 import net.shibboleth.oidfed.metadata.cache.IssuerEntityStatementCriterion;
 import net.shibboleth.oidfed.metadata.cache.SubjectEntityIDCriterion;
+import net.shibboleth.oidfed.metadata.cache.SubjectEntityStatementCriterion;
 import net.shibboleth.oidfed.metadata.cache.SubjectStatementCriterion;
 import net.shibboleth.oidfed.metadata.cache.configuration.EntityConfigurationContainer;
 import net.shibboleth.oidfed.metadata.cache.local.LocalKeyContainer;
 import net.shibboleth.oidfed.metadata.cache.trustchain.TrustChainsContainer;
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
-import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.primitive.LoggerFactory;
@@ -45,18 +46,19 @@ import net.shibboleth.shared.resolver.CriteriaSet;
 
 /**
  * Default criteria set lookup strategy for {@link BaseExpirableStatementContainer} that fetches the issuer
- * entity statement via trust chain cache or via entity configuration cache if the entity is locally trusted.
+ * entity statement via trust chain cache or via entity configuration cache if the entity is locally trusted. In that
+ * case the entity configuration is verified against the local trust anchor cache.
  */
 @ThreadSafeAfterInit
 public class DefaultTrustMarkValidationCriteriaSetLookupFunction
-    extends AbstractIdentifiableInitializableComponent
+    extends AbstractTrustEngineSignatureValidationComponent
     implements Function<BaseExpirableStatementContainer<?>, CriteriaSet> {
 
     /** Class logger. */
     @Nonnull
     private Logger log = LoggerFactory.getLogger(DefaultTrustMarkValidationCriteriaSetLookupFunction.class);
 
-    /** Cache used to fetch the issuer entity configuration of non-locally trusted entities. */
+    /** Cache used to fetch the issuer entity configuration of entities that are not locally trusted. */
     @NonnullAfterInit private MetadataCache<TrustChainsContainer> trustChainCache;
 
     /** Cache used to fetch the isser entity configuration of locally trusted entities. */
@@ -66,9 +68,9 @@ public class DefaultTrustMarkValidationCriteriaSetLookupFunction
     @NonnullAfterInit private MetadataCache<Map<String, LocalKeyContainer>> localTrustAnchorsCache;
 
     /**
-     * Set the cache used to fetch the issuer entity configuration of non-locally trusted entities.
+     * Set the cache used to fetch the issuer entity configuration of entities that are not locally trusted.
      * 
-     * @param cache cache used to fetch the issuer entity configuration of non-locally trusted entities.
+     * @param cache cache used to fetch the issuer entity configuration of entities that are not locally trusted
      */
     public void setTrustChainCache(@Nonnull final MetadataCache<TrustChainsContainer> cache) {
         checkSetterPreconditions();
@@ -117,7 +119,7 @@ public class DefaultTrustMarkValidationCriteriaSetLookupFunction
             final BaseJWTWrapper<?> statement = metadataContainer.getStatement();
             assert statement != null;
             final SubjectStatementCriterion subjectCriterion = new SubjectStatementCriterion(statement);
-            final IssuerEntityStatementCriterion issuerCriterion = getIssuerCriterion(statement);
+            final IssuerEntityStatementCriterion issuerCriterion = getIssuerCriterion(statement, metadataContainer);
             if (issuerCriterion == null) {
                 log.debug("Issuer statement could not be fetched, returning null");
                 return null;
@@ -132,10 +134,12 @@ public class DefaultTrustMarkValidationCriteriaSetLookupFunction
      * Fetch the issuer entity configuration from the metadata cache and initialize the criterion.
      * 
      * @param statement the entity statement whose issuer is fetched
+     * @param metadataContainer the metadata container containing the statement
      * @return the issuer entity configuration, or null if could not be fetched
      */
     @Nullable protected IssuerEntityStatementCriterion getIssuerCriterion(
-            @Nonnull final BaseJWTWrapper<?> statement) {
+            @Nonnull final BaseJWTWrapper<?> statement,
+            @Nonnull final BaseExpirableStatementContainer<?> metadataContainer) {
         final String issuer = statement.getIssuer();
         final CriteriaSet criteria = new CriteriaSet(new SubjectEntityIDCriterion(issuer));
         if (isLocallyTrusted(issuer)) {
@@ -143,8 +147,15 @@ public class DefaultTrustMarkValidationCriteriaSetLookupFunction
                 final List<EntityConfigurationContainer> result = entityConfigurationCache.get(criteria);
                 if (!result.isEmpty()) {
                     final EntityConfiguration issuerStatement = result.get(0).getStatement();
-                    assert issuerStatement != null;
-                    return new IssuerEntityStatementCriterion(issuerStatement);
+                    if (issuerStatement != null) {
+                        final var anchorCriteria = new CriteriaSet(
+                                new SubjectEntityStatementCriterion(issuerStatement));
+                        if (validateJwt(statement.getJwt(), anchorCriteria, metadataContainer.getEntityId())) {
+                            return new IssuerEntityStatementCriterion(issuerStatement);
+                        }
+                        log.warn("Could not validate the issuer entity configuration against trust engine");
+                        return null;
+                    }
                 }
             } catch (final MetadataCacheException e) {
                 log.debug("Error while fetching issuer entity configuration for {}", issuer, e);

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


More information about the commits mailing list