[java-idp-plugin-oidc-op-oidfed] branch dev/CACHE-REFACTOR updated: Initial support for the metadata_policy_crit claim in subordinate statements

Codeberg noreply at shibboleth.net
Mon Jan 26 09:11:58 UTC 2026


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

codeberg pushed a commit to branch dev/CACHE-REFACTOR
in repository java-idp-plugin-oidc-op-oidfed.

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

The following commit(s) were added to refs/heads/dev/CACHE-REFACTOR by this push:
     new 8976a09  Initial support for the  metadata_policy_crit claim in subordinate statements
8976a09 is described below

commit 8976a093a143ebb181c39f7ba01805997b519d63
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Mon Jan 26 11:11:17 2026 +0200

    Initial support for the  metadata_policy_crit claim in subordinate statements
    
    - Add getOperatorName() method to the federation metadata policy operators to identify the operator
    - Refactored DefaultEntityStatementContentValidationCondition to be able to feed PRC to claims validators
      - PRC is fetched via HttpServletRequest attributes (default binding key)
    - MetadataPolicyCritClaimsValidator expoits the list of supported operators
      - List may be endpoint specific: the default function exploits inbound message class (via PRC) for supplying the desired list
        - The global default may be defined via idp.oidfed.authorize.MetadataPolicyOperators (automatic registration)
        - Resolve Entity: idp.oidfed.resolve-entity.MetadataPolicyOperators
        - Explicit registration: idp.oidfed.register.MetadataPolicyOperators
        - All default to shibboleth.oidfed.StandardMetadataPolicyOperators
---
 ...tEntityStatementContentValidationCondition.java |  45 ++++++++-
 .../policy/FederationMetadataPolicyOperator.java   |   8 ++
 ...DefaultFederationMetadataPolicyAddOperator.java |   6 ++
 ...ultFederationMetadataPolicyDefaultOperator.java |   6 ++
 ...tFederationMetadataPolicyEssentialOperator.java |   6 ++
 ...faultFederationMetadataPolicyOneOfOperator.java |   6 ++
 ...ltFederationMetadataPolicySubsetOfOperator.java |   6 ++
 ...FederationMetadataPolicySupersetOfOperator.java |   6 ++
 ...faultFederationMetadataPolicyValueOperator.java |   6 ++
 ...faultMetadataPolicyOperatorsLookupStrategy.java | 103 ++++++++++++++++++++
 .../impl/MetadataPolicyCritClaimsValidator.java    | 105 +++++++++++++++++++++
 .../META-INF/net.shibboleth.idp/postconfig.xml     |  28 +++++-
 .../flow/oidfed/AbstractFederationFlowTest.java    |  23 +++++
 .../AuthorizeFlowAutomaticRegistrationTest.java    |  19 ++++
 .../profile/flow/oidfed/RegistrationFlowTest.java  |  12 +++
 .../profile/flow/oidfed/ResolveEntityFlowTest.java |  40 ++++++++
 16 files changed, 417 insertions(+), 8 deletions(-)

diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/DefaultEntityStatementContentValidationCondition.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/DefaultEntityStatementContentValidationCondition.java
index bdd173a..4513abe 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/DefaultEntityStatementContentValidationCondition.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/DefaultEntityStatementContentValidationCondition.java
@@ -15,6 +15,7 @@
 package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote;
 
 import java.text.ParseException;
+import java.util.Optional;
 import java.util.function.BiPredicate;
 
 import javax.annotation.Nonnull;
@@ -25,20 +26,24 @@ import org.slf4j.Logger;
 
 import com.nimbusds.jwt.JWTClaimsSet;
 
+import jakarta.servlet.http.HttpServletRequest;
 import net.shibboleth.oidc.jwt.claims.ClaimsValidator;
 import net.shibboleth.oidc.jwt.claims.JWTValidationException;
 import net.shibboleth.oidc.metadata.filter.MetadataFilterContext;
 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;
+import net.shibboleth.shared.primitive.NonnullSupplier;
 
 /**
  * Default content validating filter for entity statement. Verifies that the 
  * {@link RemoteEntityConfigurationContainer#getEntityId()} matches with the subject of the entity statement and
- * validates the claims via configurable claims validator. Note that an empty {@link ProfileRequestContext} is fed to
- * the claims validator.
+ * validates the claims via configurable claims validator. The {@link ProfileRequestContext} that is fed to the claims
+ * validator is fetched from the {@link HttpServletRequest} attributes. An empty context is fed if the attribute was
+ * null.
  */
 @ThreadSafeAfterInit
 public class DefaultEntityStatementContentValidationCondition
@@ -52,6 +57,9 @@ public class DefaultEntityStatementContentValidationCondition
     /** The claims validator to use for validating the entity statement claims. */
     @NonnullAfterInit private ClaimsValidator claimsValidator;
 
+    /** Supplier for the Current HTTP request, if available. */
+    @NonnullAfterInit private NonnullSupplier<HttpServletRequest> httpServletRequestSupplier;
+
     /**
      * Set the claims validator to use for validating the entity statement claims.
      * 
@@ -62,6 +70,28 @@ public class DefaultEntityStatementContentValidationCondition
         claimsValidator = Constraint.isNotNull(validator, "Claims validator cannot be null");
     }
 
+    /**
+     * Set the current HTTP request Supplier.
+     *
+     * @param requestSupplier Supplier for the current HTTP request
+     */
+    public void setHttpServletRequestSupplier(@Nonnull final NonnullSupplier<HttpServletRequest> requestSupplier) {
+        checkSetterPreconditions();
+        httpServletRequestSupplier = Constraint.isNotNull(requestSupplier, "Http servlet request supplier cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void doInitialize() throws ComponentInitializationException {
+        super.doInitialize();
+        if (claimsValidator == null) {
+            throw new ComponentInitializationException("Claims validator cannot be null");
+        }
+        if (httpServletRequestSupplier == null) {
+            throw new ComponentInitializationException("Http servlet request supplier cannot be null");
+        }
+    }
+
     /** {@inheritDoc} */
     @Override
     public boolean test(@Nullable final BaseExpirableStatementContainer<?> responseContainer,
@@ -79,11 +109,20 @@ public class DefaultEntityStatementContentValidationCondition
                     wrapper.getParsedPayload().getSubject(), responseContainer.getEntityId());
             return false;
         }
+        final ProfileRequestContext profileRequestContext =
+                Optional.ofNullable(httpServletRequestSupplier.get().getAttribute(ProfileRequestContext.BINDING_KEY))
+                .filter(ProfileRequestContext.class::isInstance)
+                .map(ProfileRequestContext.class::cast)
+                .orElse(null);
+        if (profileRequestContext == null) {
+            log.warn("Could not resolve profile request context, supplying an empty one to claims validators");
+        }
 
         try {
             final JWTClaimsSet claimsSet = wrapper.getJwt().getJWTClaimsSet();
             assert claimsSet != null;
-            claimsValidator.validate(claimsSet, new ProfileRequestContext());
+            claimsValidator.validate(claimsSet,
+                    profileRequestContext != null ? profileRequestContext : new ProfileRequestContext());
         } catch (final JWTValidationException | ParseException e) {
             log.warn("Claims validation failed for entity statement {}", responseContainer.getEntityId(), e);
             return false;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/FederationMetadataPolicyOperator.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/FederationMetadataPolicyOperator.java
index c6a367a..dbfd708 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/FederationMetadataPolicyOperator.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/FederationMetadataPolicyOperator.java
@@ -18,6 +18,7 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import net.shibboleth.oidc.metadata.policy.MetadataPolicy;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.logic.ConstraintViolationException;
 
 /**
@@ -27,6 +28,13 @@ import net.shibboleth.shared.logic.ConstraintViolationException;
  */
 public interface FederationMetadataPolicyOperator {
 
+    /**
+     * The unique case-sensitive name of this operator.
+     *
+     * @return the operator name.
+     */
+    @Nonnull @NotEmpty public String getOperatorName();
+
     /**
      * Validate whether the operator is compatible with the other operators in the policy.
      * 
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyAddOperator.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyAddOperator.java
index e30ffc4..0995e74 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyAddOperator.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyAddOperator.java
@@ -25,6 +25,7 @@ import org.slf4j.Logger;
 
 import net.shibboleth.oidc.metadata.policy.MetadataPolicy;
 import net.shibboleth.oidc.metadata.policy.impl.MetadataPolicyHelper;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.logic.ConstraintViolationException;
 import net.shibboleth.shared.primitive.LoggerFactory;
@@ -37,6 +38,11 @@ public class DefaultFederationMetadataPolicyAddOperator extends AbstractFederati
     /** Class logger. */
     @Nonnull private final Logger log = LoggerFactory.getLogger(DefaultFederationMetadataPolicyAddOperator.class);
 
+    /** {@inheritDoc} */
+    @Nonnull @NotEmpty public String getOperatorName() {
+        return "add";
+    }
+
     /** {@inheritDoc} */
     @Override
     @Nullable public Object apply(@Nullable final Object candidate, @Nonnull final MetadataPolicy policy)
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyDefaultOperator.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyDefaultOperator.java
index 89bf483..f0ebe6b 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyDefaultOperator.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyDefaultOperator.java
@@ -18,6 +18,7 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import net.shibboleth.oidc.metadata.policy.MetadataPolicy;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.logic.ConstraintViolationException;
 
 /**
@@ -25,6 +26,11 @@ import net.shibboleth.shared.logic.ConstraintViolationException;
  */
 public class DefaultFederationMetadataPolicyDefaultOperator extends AbstractFederationMetadataPolicyOperator {
 
+    /** {@inheritDoc} */
+    @Nonnull @NotEmpty public String getOperatorName() {
+        return "default";
+    }
+
     /** {@inheritDoc} */
     @Override
     @Nullable public Object apply(@Nullable final Object candidate, @Nonnull final MetadataPolicy policy)
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyEssentialOperator.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyEssentialOperator.java
index 8a1efc7..3167a63 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyEssentialOperator.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyEssentialOperator.java
@@ -18,6 +18,7 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import net.shibboleth.oidc.metadata.policy.MetadataPolicy;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.logic.ConstraintViolationException;
 
 /**
@@ -25,6 +26,11 @@ import net.shibboleth.shared.logic.ConstraintViolationException;
  */
 public class DefaultFederationMetadataPolicyEssentialOperator extends AbstractFederationMetadataPolicyOperator {
 
+    /** {@inheritDoc} */
+    @Nonnull @NotEmpty public String getOperatorName() {
+        return "essential";
+    }
+
     /** {@inheritDoc} */
     @Override
     @Nullable public Object apply(@Nullable final Object candidate, @Nonnull final MetadataPolicy policy)
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyOneOfOperator.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyOneOfOperator.java
index 04a39f0..5165e0b 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyOneOfOperator.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyOneOfOperator.java
@@ -22,6 +22,7 @@ import javax.annotation.Nullable;
 import org.slf4j.Logger;
 
 import net.shibboleth.oidc.metadata.policy.MetadataPolicy;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.logic.ConstraintViolationException;
 import net.shibboleth.shared.primitive.LoggerFactory;
 
@@ -33,6 +34,11 @@ public class DefaultFederationMetadataPolicyOneOfOperator extends AbstractFedera
     /** Class logger. */
     @Nonnull private final Logger log = LoggerFactory.getLogger(DefaultFederationMetadataPolicyOneOfOperator.class);
 
+    /** {@inheritDoc} */
+    @Nonnull @NotEmpty public String getOperatorName() {
+        return "one_of";
+    }
+
     /** {@inheritDoc} */
     @Override
     @Nullable public Object apply(@Nullable final Object candidate, @Nonnull final MetadataPolicy policy)
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicySubsetOfOperator.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicySubsetOfOperator.java
index f5a05be..1668048 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicySubsetOfOperator.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicySubsetOfOperator.java
@@ -23,6 +23,7 @@ import org.slf4j.Logger;
 
 import net.shibboleth.oidc.metadata.policy.MetadataPolicy;
 import net.shibboleth.oidc.metadata.policy.impl.MetadataPolicyHelper;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.logic.ConstraintViolationException;
 import net.shibboleth.shared.primitive.LoggerFactory;
@@ -35,6 +36,11 @@ public class DefaultFederationMetadataPolicySubsetOfOperator extends AbstractFed
     /** Class logger. */
     @Nonnull private final Logger log = LoggerFactory.getLogger(DefaultFederationMetadataPolicySubsetOfOperator.class);
 
+    /** {@inheritDoc} */
+    @Nonnull @NotEmpty public String getOperatorName() {
+        return "subset_of";
+    }
+
     /** {@inheritDoc} */
     @Override
     @Nullable public Object apply(@Nullable final Object candidate, @Nonnull final MetadataPolicy policy)
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicySupersetOfOperator.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicySupersetOfOperator.java
index 5cea512..fae223e 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicySupersetOfOperator.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicySupersetOfOperator.java
@@ -23,6 +23,7 @@ import org.slf4j.Logger;
 
 import net.shibboleth.oidc.metadata.policy.MetadataPolicy;
 import net.shibboleth.oidc.metadata.policy.impl.MetadataPolicyHelper;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.logic.ConstraintViolationException;
 import net.shibboleth.shared.primitive.LoggerFactory;
@@ -35,6 +36,11 @@ public class DefaultFederationMetadataPolicySupersetOfOperator extends AbstractF
     /** Class logger. */
     @Nonnull private final Logger log = LoggerFactory.getLogger(DefaultFederationMetadataPolicySupersetOfOperator.class);
 
+    /** {@inheritDoc} */
+    @Nonnull @NotEmpty public String getOperatorName() {
+        return "superset_of";
+    }
+
     /** {@inheritDoc} */
     @Override
     @Nullable public Object apply(@Nullable final Object candidate, @Nonnull final MetadataPolicy policy)
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyValueOperator.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyValueOperator.java
index fee597c..6fdaefb 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyValueOperator.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/policy/impl/DefaultFederationMetadataPolicyValueOperator.java
@@ -24,6 +24,7 @@ import org.slf4j.Logger;
 
 import net.shibboleth.oidc.metadata.policy.MetadataPolicy;
 import net.shibboleth.oidc.metadata.policy.impl.MetadataPolicyHelper;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.logic.ConstraintViolationException;
 import net.shibboleth.shared.primitive.LoggerFactory;
 
@@ -35,6 +36,11 @@ public class DefaultFederationMetadataPolicyValueOperator extends AbstractFedera
     /** Class logger. */
     @Nonnull private final Logger log = LoggerFactory.getLogger(DefaultFederationMetadataPolicyValueOperator.class);
 
+    /** {@inheritDoc} */
+    @Nonnull @NotEmpty public String getOperatorName() {
+        return "value";
+    }
+
     /** {@inheritDoc} */
     @Override
     @Nullable public Object apply(@Nullable final Object candidate, @Nonnull final MetadataPolicy policy)
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/security/jwt/claims/impl/DefaultMetadataPolicyOperatorsLookupStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/security/jwt/claims/impl/DefaultMetadataPolicyOperatorsLookupStrategy.java
new file mode 100644
index 0000000..8788bdd
--- /dev/null
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/security/jwt/claims/impl/DefaultMetadataPolicyOperatorsLookupStrategy.java
@@ -0,0 +1,103 @@
+/*
+ * 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.idp.plugin.oidc.op.oidfed.security.jwt.claims.impl;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.policy.FederationMetadataPolicyOperator;
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
+
+/**
+ * Default lookup strategy to resolve list of supported metadata policy operators.
+ */
+public class DefaultMetadataPolicyOperatorsLookupStrategy extends AbstractIdentifiableInitializableComponent 
+    implements Function<ProfileRequestContext, List<FederationMetadataPolicyOperator>> {
+
+    /** Class logger. */
+    @Nonnull private Logger log = LoggerFactory.getLogger(DefaultMetadataPolicyOperatorsLookupStrategy.class);
+
+    /** Map of supported operators by inbound message class name. */
+    @NonnullAfterInit private Map<String, List<FederationMetadataPolicyOperator>> supportedOperators;
+
+    /** List of default supported operators if inbound message class name was not mapped. */
+    @NonnullAfterInit private List<FederationMetadataPolicyOperator> defaultSupportedOperators;
+
+    /**
+     * Set the map of supported operators by inbound message class name.
+     * 
+     * @param operators map of supported operators
+     */
+    public void setSupportedOperators(@Nonnull final Map<String, List<FederationMetadataPolicyOperator>> operators) {
+        checkSetterPreconditions();
+        supportedOperators = Constraint.isNotNull(operators, "Map of supported operators cannot be null");
+    }
+
+    /**
+     * Set the list of default supported operators if inbound message class name was not mapped.
+     * 
+     * @param operators default list of supported operators
+     */
+    public void setDefaultSupportedOperators(@Nonnull List<FederationMetadataPolicyOperator> operators) {
+        checkSetterPreconditions();
+        defaultSupportedOperators =
+                Constraint.isNotNull(operators, "Default list of supported operators cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    protected void doInitialize() throws ComponentInitializationException {
+        super.doInitialize();
+        if (supportedOperators == null) {
+            throw new ComponentInitializationException("Map of supported operators cannot be null");
+        }
+        if (defaultSupportedOperators == null) {
+            throw new ComponentInitializationException("Default list of supported operators cannot be null");
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override @Nullable
+    public List<FederationMetadataPolicyOperator> apply(@Nullable final ProfileRequestContext profileRequestContext) {
+        checkComponentActive();
+        if (profileRequestContext == null || profileRequestContext.getInboundMessageContext() == null
+                || profileRequestContext.ensureInboundMessageContext().getMessage() == null)  {
+            log.warn("No inbound message resolved, returning default list of supported operators");
+        } else {
+            final Object message = profileRequestContext.ensureInboundMessageContext().getMessage();
+            assert message != null;
+            final String messageClassName = message.getClass().getCanonicalName();
+            if (supportedOperators.containsKey(messageClassName)) {
+                log.debug("Found message {} specific list of supported operators {}", messageClassName,
+                        supportedOperators.get(messageClassName));
+                return supportedOperators.get(messageClassName);
+            }
+            log.trace("No messsage class {} specific list found, returning default list of supported operators",
+                    messageClassName);
+        }
+        return defaultSupportedOperators;
+    }
+
+}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/security/jwt/claims/impl/MetadataPolicyCritClaimsValidator.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/security/jwt/claims/impl/MetadataPolicyCritClaimsValidator.java
new file mode 100644
index 0000000..d28a348
--- /dev/null
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/security/jwt/claims/impl/MetadataPolicyCritClaimsValidator.java
@@ -0,0 +1,105 @@
+/*
+ * 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.idp.plugin.oidc.op.oidfed.security.jwt.claims.impl;
+
+import java.text.ParseException;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import com.nimbusds.jwt.JWTClaimsSet;
+
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.policy.FederationMetadataPolicyOperator;
+import net.shibboleth.oidc.jwt.claims.AbstractClaimsValidator;
+import net.shibboleth.oidc.jwt.claims.ClaimsValidator;
+import net.shibboleth.oidc.jwt.claims.JWTValidationException;
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
+import net.shibboleth.shared.collection.CollectionSupport;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.Constraint;
+
+/**
+ * A {@link ClaimsValidator} for validating that all the metadata_policy_crit is not an empty array and all the values
+ * are recognized by the resolved list of supported metadata policy operators.
+ */
+ at ThreadSafeAfterInit
+public class MetadataPolicyCritClaimsValidator extends AbstractClaimsValidator {
+
+    /** The list of standard operators that cannot be included in the metadata_policy_crit array. */
+    public static final List<String> STANDARD_OPERATORS = CollectionSupport.listOf(
+            "value", "add", "default", "one_of", "subset_of", "superset_of", "essential");
+
+    /** The lookup strategy for the list of supported metadata policy operators . */
+    @NonnullAfterInit private
+    Function<ProfileRequestContext, List<FederationMetadataPolicyOperator>> supportedOperatorsLookupStrategy;
+
+    /**
+     * Set the lookup strategy for the list of supported metadata policy operators.
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setSupportedOperatorsLookupStrategy(
+            @Nonnull final Function<ProfileRequestContext, List<FederationMetadataPolicyOperator>> strategy) {
+        checkSetterPreconditions();
+        supportedOperatorsLookupStrategy =
+                Constraint.isNotNull(strategy, "Supported metadata policy operators lookup strategy cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    protected void doInitialize() throws ComponentInitializationException {
+        super.doInitialize();
+        if (supportedOperatorsLookupStrategy == null) {
+            throw new ComponentInitializationException(
+                    "Supported metadata policy operators lookup strategy cannot be null");
+        }
+    }
+
+    /** {@inheritDoc} */
+    protected void doValidate(@Nonnull final JWTClaimsSet claims, 
+            @Nonnull final ProfileRequestContext context) throws JWTValidationException {
+        final List<String> values;
+        try {
+            values = claims.getStringListClaim("metadata_policy_crit");
+        } catch (final ParseException e) {
+            throw new JWTValidationException("Could not parse metadata_policy_crit into a list of strings");
+        }
+        final List<String> supportedValues = Optional.ofNullable(supportedOperatorsLookupStrategy.apply(context))
+                .orElse(CollectionSupport.emptyList())
+                .stream().map(operator -> operator.getOperatorName()).toList();
+        if (values != null) {
+            if (values.isEmpty()) {
+                throw new JWTValidationException("Empty array is not allowed for metadata_policy_crit");
+            }
+            for (final String value : values) {
+                if (values.indexOf(value) != values.lastIndexOf(value)) {
+                    throw new JWTValidationException(
+                            "Claim " + value + " is included more than once in metadata_policy_crit");
+                }
+                if (STANDARD_OPERATORS.contains(value)) {
+                    throw new JWTValidationException(
+                            "Claim " + value + " is standard operator and is not allowed in metadata_policy_crit");
+                }
+                if (!supportedValues.contains(value)) {
+                    throw new JWTValidationException( "Claim " + value + " is not recognized in metadata_policy_crit");
+                }
+            }
+        }
+    }
+}
diff --git a/idp-oidfed-op-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml b/idp-oidfed-op-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
index 34c4020..1f74889 100644
--- a/idp-oidfed-op-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
+++ b/idp-oidfed-op-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
@@ -134,7 +134,8 @@
                             </property>
                         </bean>
                         <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.DefaultEntityStatementContentValidationCondition"
-                            p:claimsValidator-ref="%{idp.oidfed.entityConfiguration.claimsValidator:shibboleth.oidfed.DefaultEntityConfigurationClaimsValidator}"/>
+                            p:claimsValidator-ref="%{idp.oidfed.entityConfiguration.claimsValidator:shibboleth.oidfed.DefaultEntityConfigurationClaimsValidator}"
+                            p:httpServletRequestSupplier-ref="shibboleth.HttpServletRequestSupplier"/>
                     </util:list>
                 </property>
             </bean>
@@ -222,7 +223,8 @@
                             </property>
                         </bean>
                         <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.DefaultEntityStatementContentValidationCondition"
-                            p:claimsValidator-ref="%{idp.oidfed.subordinateStatement.claimsValidator:shibboleth.oidfed.DefaultSubordinateStatementClaimsValidator}"/>
+                            p:claimsValidator-ref="%{idp.oidfed.subordinateStatement.claimsValidator:shibboleth.oidfed.DefaultSubordinateStatementClaimsValidator}"
+                            p:httpServletRequestSupplier-ref="shibboleth.HttpServletRequestSupplier"/>
                     </util:list>
                 </property>
             </bean>
@@ -274,6 +276,19 @@
                     p:requiredClaims="jwks" />
                 <bean class="net.shibboleth.oidc.security.jwt.claims.impl.ExpiryClaimsValidator"
                     p:clockSkew="%{idp.policy.clockSkew:PT1M}" />
+                <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.security.jwt.claims.impl.MetadataPolicyCritClaimsValidator">
+                    <property name="supportedOperatorsLookupStrategy">
+                        <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.security.jwt.claims.impl.DefaultMetadataPolicyOperatorsLookupStrategy"
+                            p:defaultSupportedOperators-ref="#{'%{idp.oidfed.authorize.MetadataPolicyOperators:shibboleth.oidfed.StandardMetadataPolicyOperators}'.trim()}">
+                            <property name="supportedOperators">
+                                <util:map>
+                                    <entry key="net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.ResolveEntityRequest" value-ref="#{'%{idp.oidfed.resolve-entity.MetadataPolicyOperators:shibboleth.oidfed.StandardMetadataPolicyOperators}'.trim()}" />
+                                    <entry key="net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.ExplicitClientRegistrationRequest" value-ref="#{'%{idp.oidfed.register.MetadataPolicyOperators:shibboleth.oidfed.StandardMetadataPolicyOperators}'.trim()}" />
+                                </util:map>
+                            </property>
+                        </bean>
+                    </property>
+                </bean>
                 <bean class="net.shibboleth.oidc.security.jwt.claims.impl.ProhibitedClaimsValidator"
                     p:prohibitedClaims="authority_hints" />
                 <bean class="net.shibboleth.oidc.security.jwt.claims.impl.ProhibitedClaimsValidator"
@@ -375,7 +390,8 @@
                             </property>
                         </bean>
                         <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.DefaultEntityStatementContentValidationCondition"
-                            p:claimsValidator-ref="%{idp.oidfed.remoteResolver.claimsValidator:shibboleth.oidfed.DefaultResolveEntityResponseClaimsValidator}"/>
+                            p:claimsValidator-ref="%{idp.oidfed.remoteResolver.claimsValidator:shibboleth.oidfed.DefaultResolveEntityResponseClaimsValidator}"
+                            p:httpServletRequestSupplier-ref="shibboleth.HttpServletRequestSupplier"/>
                     </util:list>
                 </property>
             </bean>
@@ -501,7 +517,8 @@
                             </property>
                         </bean>
                         <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.DefaultEntityStatementContentValidationCondition"
-                            p:claimsValidator-ref="%{idp.oidfed.trustMarkStatus.claimsValidator:shibboleth.oidfed.DefaultTrustMarkStatusClaimsValidator}"/>
+                            p:claimsValidator-ref="%{idp.oidfed.trustMarkStatus.claimsValidator:shibboleth.oidfed.DefaultTrustMarkStatusClaimsValidator}"
+                            p:httpServletRequestSupplier-ref="shibboleth.HttpServletRequestSupplier"/>
                     </util:list>
                 </property>
             </bean>
@@ -586,7 +603,8 @@
                             </property>
                         </bean>
                         <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.DefaultEntityStatementContentValidationCondition"
-                            p:claimsValidator-ref="%{idp.oidfed.trustMark.claimsValidator:shibboleth.oidfed.DefaultTrustMarkClaimsValidator}"/>
+                            p:claimsValidator-ref="%{idp.oidfed.trustMark.claimsValidator:shibboleth.oidfed.DefaultTrustMarkClaimsValidator}"
+                            p:httpServletRequestSupplier-ref="shibboleth.HttpServletRequestSupplier"/>
                     </util:list>
                 </property>
             </bean>
diff --git a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AbstractFederationFlowTest.java b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AbstractFederationFlowTest.java
index b56da5c..fb41140 100644
--- a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AbstractFederationFlowTest.java
+++ b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AbstractFederationFlowTest.java
@@ -390,13 +390,24 @@ public class AbstractFederationFlowTest extends AbstractOidcFlowTest {
         return subordinateStatement(issuer, metadata, leafKey);
     }
 
+    protected String subordinateStatement(final String issuer, final Map<String, Object> metadata,
+            final List<String> metadataPolicyCrit) {
+        return subordinateStatement(issuer, metadata, metadataPolicyCrit, leafKey);
+    }
+
     protected String subordinateStatement(final String issuer, final Map<String, Object> metadata,
             final JWK subjectKey) {
+        return subordinateStatement(issuer, metadata, null, subjectKey);
+    }
+
+    protected String subordinateStatement(final String issuer, final Map<String, Object> metadata,
+            final List<String> metadataPolicyCrit, final JWK subjectKey) {
         final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().issuer(anchorId).subject(issuer)
                 .issueTime(Date.from(Instant.now()))
                 .expirationTime(Date.from(Instant.now().plusSeconds(300)))
                 .claim("jwks", new JWKSet(subjectKey).toJSONObject(true))
                 .claim("metadata", metadata)
+                .claim("metadata_policy_crit", metadataPolicyCrit)
                 .build();
         final EntityStatement<?> rpConfiguration =
                 TrustChainTestUtil.entityStatement(JWSAlgorithm.RS256, trustedAnchorKey, claimsSet);
@@ -544,6 +555,18 @@ public class AbstractFederationFlowTest extends AbstractOidcFlowTest {
         }
     }
 
+    protected void rpConfigureMockHttpClientWithMetadataCrit(final String clientId, final List<String> crit) {
+        try {
+            mapResponse(entityConfigurationUrl(clientId), mockResponse(rpEntityConfiguration(clientId)));
+            mapResponse(entityConfigurationUrl(anchorId), mockResponse(trustedAnchorConfiguration()));
+            mapResponse(subordinateStatementUrl(anchorFetchEndpoint, clientId),
+                    mockResponse(subordinateStatement(clientId, Map.of("openid_relying_party",
+                            new OIDCClientMetadata().toJSONObject()), crit)));
+        } catch (UnsupportedOperationException | IOException | URISyntaxException e) {
+            Assert.fail("Could not initialize mock HTTP client", e);
+        }
+    }
+
     protected void rpResolveEntityConfigureMockHttpClient(final String clientId) {
         final OIDCClientMetadata metadata = new OIDCClientMetadata();
         metadata.setRedirectionURI(URI.create(redirectUri));
diff --git a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AuthorizeFlowAutomaticRegistrationTest.java b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AuthorizeFlowAutomaticRegistrationTest.java
index 4ce2b70..f7f3ebd 100644
--- a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AuthorizeFlowAutomaticRegistrationTest.java
+++ b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AuthorizeFlowAutomaticRegistrationTest.java
@@ -53,6 +53,7 @@ import net.shibboleth.idp.plugin.oidc.op.profile.flow.AuthorizeFlowTest;
 import net.shibboleth.idp.plugin.oidc.op.profile.logic.DefaultPushedAuthorizationRequestUriSerializationFunction;
 import net.shibboleth.idp.plugin.oidc.op.token.support.AuthorizeCodeClaimsSet;
 import net.shibboleth.idp.session.SessionException;
+import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.collection.Pair;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.security.DataSealerException;
@@ -117,6 +118,24 @@ public class AuthorizeFlowAutomaticRegistrationTest extends AbstractFederationFl
         Assert.assertEquals(unwrapTrustChainFromAuthorizeCode(successResponse), List.of(clientId, anchorId));
     }
 
+    @Test
+    public void testWithValidTrustChain_signedRequestObject_emptyMetadataPolicyCrit()
+            throws IOException, UnsupportedOperationException, URISyntaxException {
+        final String clientId = uniqueClientId();
+        rpConfigureMockHttpClientWithMetadataCrit(clientId, CollectionSupport.emptyList());
+        final FlowExecutionResult result =
+                launchAuthenticationRequest(clientId, "openid profile", signedRequestObject(Map.of(
+                        "iss", clientId,
+                        "client_id", clientId,
+                        "aud", issuer,
+                        "exp", Instant.now().plus(Duration.ofMinutes(5)).toEpochMilli(),
+                        "jti", UUID.randomUUID(),
+                        "response_type", "code",
+                        "scope", "openid profile",
+                        "redirect_uri", redirectUri)));
+        Assert.assertEquals(result.getOutcome().getId(), "ErrorView");
+    }
+
     @Test
     public void testWithValidTrustChain_resolveApi_signedRequestObject()
             throws IOException, UnsupportedOperationException, URISyntaxException {
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 b3e39cc..18c0314 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
@@ -51,6 +51,7 @@ import net.shibboleth.idp.plugin.oidc.op.oidfed.TrustChainTestUtil;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.ExplicitClientRegistrationResponse;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
 import net.shibboleth.oidc.metadata.impl.BaseStorageServiceClientInformationComponent;
+import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.collection.Pair;
 
 /**
@@ -118,6 +119,17 @@ public class RegistrationFlowTest extends AbstractFederationFlowTest {
         verifyAuthorizeEndpoint(clientId, redirectUri);
     }
 
+    @Test
+    public void testValidEntityConfiguration_emptyMetadataPolicyCrit() throws Exception {
+        final String clientId = uniqueClientId();
+        rpConfigureMockHttpClientWithMetadataCrit(clientId, CollectionSupport.emptyList());
+        setRequest("POST", rpEntityConfiguration(clientId), "application/entity-statement+jwt");
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        verify(federationHttpClient, times(0)).executeOpen(any(),
+                argThat(new RequestUriMatcher(entityConfigurationUrl(clientId))), any());
+        assertErrorCode(result, "invalid_client");
+    }
+
     @Test
     public void testValidEntityConfiguration_verifyPar() throws Exception {
         final String clientId = uniqueClientId();
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 05f1322..bd8a31d 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
@@ -14,6 +14,10 @@
 
 package net.shibboleth.idp.plugin.oidc.op.profile.flow.oidfed;
 
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.time.Instant;
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
@@ -22,10 +26,15 @@ import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import com.nimbusds.jose.JOSEObjectType;
+import com.nimbusds.jose.JWSAlgorithm;
+import com.nimbusds.jose.jwk.JWKSet;
+import com.nimbusds.jwt.JWTClaimsSet;
 import com.nimbusds.jwt.SignedJWT;
 import com.nimbusds.oauth2.sdk.Response;
 
+import net.shibboleth.idp.plugin.oidc.op.oidfed.TrustChainTestUtil;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.ResolveEntityResponse;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
 import net.shibboleth.oidc.profile.messaging.JSONErrorResponse;
 
 import net.minidev.json.JSONObject;
@@ -129,6 +138,37 @@ public class ResolveEntityFlowTest extends AbstractFederationFlowTest {
         assertErrorCode(result, "invalid_metadata");
     }
 
+    @Test
+    public void testOPWithTrustedTrustAnchor_emptyMetadataPolicyCrit() throws Exception {
+        request.setMethod("GET");
+        final String entityId = uniqueClientId();
+        final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().issuer(anchorId).subject(entityId)
+                .issueTime(Date.from(Instant.now()))
+                .expirationTime(Date.from(Instant.now().plusSeconds(300)))
+                .claim("jwks", new JWKSet(leafKey).toJSONObject(true))
+                .claim("metadata", Map.of("openid_provider", emptyOpMetadata(entityId).toJSONObject()))
+                .build();
+        final EntityStatement<?> subordinateStatement =
+                TrustChainTestUtil.entityStatement(JWSAlgorithm.RS256, trustedAnchorKey, claimsSet);
+        try {
+            mapResponse(entityConfigurationUrl(entityId), mockResponse(opEntityConfiguration(entityId)));
+            mapResponse(entityConfigurationUrl(anchorId), mockResponse(trustedAnchorConfiguration()));
+            mapResponse(subordinateStatementUrl(anchorFetchEndpoint, entityId),
+                    mockResponse(subordinateStatement.getJwt().serialize()));
+        } catch (UnsupportedOperationException | IOException | URISyntaxException e) {
+            Assert.fail("Could not initialize mock HTTP client", e);
+        }
+        request.setQueryString("sub=" + entityId + "&trust_anchor=" + anchorId + "&entity_type=openid_provider");
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        final ResolveEntityResponse parsedResponse =
+                parseSuccessResponse(result, ResolveEntityResponse.class);
+        final SignedJWT response = parsedResponse.getJWT();
+        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"));
+    }
+
     protected JSONErrorResponse parseErrorResponse(final FlowExecutionResult result) {
         final Response response = parseResponse(result);
         Assert.assertTrue(response instanceof JSONErrorResponse);

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


More information about the commits mailing list