[java-idp-plugin-oidc-op-oidfed] 02/02: Switched the metadata wrappers in the API-module into interfaces

Codeberg noreply at shibboleth.net
Fri Dec 19 12:03:24 UTC 2025


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/6bb9fcace0609042ee31f002c0c04ded9c34b95e

commit 6bb9fcace0609042ee31f002c0c04ded9c34b95e
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Fri Dec 19 14:01:00 2025 +0200

    Switched the metadata wrappers in the API-module into interfaces
    
    - Jackson dependency could be removed from the API module
    - Implementing classes in the IMPL-module exploit Jackson
    - Also improved metadata cache containers for trust marks and remotely resolved entities
---
 idp-oidfed-op-api/pom.xml                          | 10 ---
 ...aseMetadataPayload.java => BaseJWTWrapper.java} | 36 +++++-----
 .../oidc/op/oidfed/metadata/BasePayload.java       | 70 ++----------------
 .../op/oidfed/metadata/EntityConfiguration.java    | 43 +----------
 .../oidc/op/oidfed/metadata/EntityStatement.java   | 27 ++-----
 .../op/oidfed/metadata/ResolveEntityResponse.java  | 42 +----------
 .../op/oidfed/metadata/SubordinateStatement.java   | 42 +----------
 .../plugin/oidc/op/oidfed/metadata/TrustMark.java  | 42 +----------
 .../oidc/op/oidfed/metadata/TrustMarkStatus.java   | 42 +----------
 .../payload/BaseExpirableSubjectPayload.java       | 39 ++++++++++
 .../{ => payload}/BaseMetadataPayload.java         | 24 ++-----
 .../payload/EntityConfigurationPayload.java        | 65 +++++++++++++++++
 .../metadata/payload/EntityStatementPayload.java   | 41 +++++++++++
 .../payload/ResolveEntityResponsePayload.java      | 41 +++++++++++
 .../payload/SubordinateStatementPayload.java       | 59 +++++++++++++++
 .../oidfed/metadata/payload/TrustMarkPayload.java  | 51 +++++++++++++
 .../metadata/payload/TrustMarkStatusPayload.java   | 40 +++++++++++
 .../op/oidfed/metadata/payload/claim/Metadata.java | 83 ++++++++++++++++++++++
 .../context/RelyingPartyTrustChainContext.java     |  2 +-
 .../ExplicitClientRegistrationRequestDecoder.java  |  6 +-
 ...DefaultTrustChainTrustMarksParsingStrategy.java |  2 +-
 ...ChainTrustedTrustMarkIssuersLookupStrategy.java |  2 +-
 ...tChainTrustedTrustMarkOwnersLookupStrategy.java |  2 +-
 .../remote/BaseExpirableStatementContainer.java    |  6 +-
 ...atementValidationCriteriaSetLookupFunction.java |  6 +-
 .../cache/remote/SubjectStatementCriterion.java    |  8 +--
 ...DefaultEntityConfigurationFetchingStrategy.java |  3 +-
 ...ultResolveEntityTrustChainFetchingStrategy.java |  3 +-
 ...efaultSubordinateStatementFetchingStrategy.java |  3 +-
 .../DefaultTrustChainFetchingStrategy.java         |  2 +-
 .../DefaultTrustMarkFetchingStrategy.java          |  3 +-
 .../DefaultTrustMarkStatusFetchingStrategy.java    |  3 +-
 ...ustMarkValidationCriteriaSetLookupFunction.java |  6 +-
 .../FederationPolicyConstraintHelper.java          |  2 +-
 .../impl/DefaultAllowedEntityTypesConstraint.java  |  2 +-
 .../metadata/impl/AbstractJWTWrapperImpl.java      |  8 ++-
 .../op/oidfed/metadata/impl/BasePayloadImpl.java   |  6 +-
 .../metadata/impl/EntityConfigurationImpl.java     | 22 +++---
 .../oidfed/metadata/impl/EntityStatementImpl.java  |  9 ++-
 .../metadata/impl/ResolveEntityResponseImpl.java   | 22 +++---
 .../metadata/impl/SubordinateStatementImpl.java    | 22 +++---
 .../op/oidfed/metadata/impl/TrustMarkImpl.java     | 21 +++---
 .../oidfed/metadata/impl/TrustMarkStatusImpl.java  | 22 +++---
 .../metadata/payload/claim/impl/MetadataImpl.java  |  9 +--
 .../impl/BaseExpirableSubjectPayloadImpl.java      |  7 +-
 .../payload/impl/BaseMetadataPayloadImpl.java      |  7 +-
 .../impl/EntityConfigurationPayloadImpl.java       |  8 ++-
 .../payload/impl/EntityStatementPayloadImpl.java   |  6 +-
 .../impl/ResolveEntityResponsePayloadImpl.java     |  6 +-
 .../impl/SubordinateStatementPayloadImpl.java      |  8 ++-
 .../payload/impl/TrustMarkPayloadImpl.java         |  6 +-
 .../payload/impl/TrustMarkStatusPayloadImpl.java   |  7 +-
 .../impl/AbstractTrustChainResolutionAction.java   |  5 +-
 .../impl/AddExtensionsToClientInformation.java     |  2 +-
 .../profile/impl/BuildResolveEntityResponse.java   |  2 +-
 .../oidfed/profile/impl/CallResolveEntityApi.java  | 21 +++---
 .../op/oidfed/profile/impl/ResolveTrustChains.java |  2 +-
 .../op/oidfed/profile/impl/ResolveTrustMarks.java  |  2 +-
 .../op/oidfed/profile/impl/SelectTrustChain.java   |  2 +-
 .../profile/impl/StoreAutomaticRegistration.java   |  2 +-
 ...eAutomaticRegistrationProfileConfiguration.java |  5 +-
 .../profile/impl/ValidateProvidedTrustChain.java   |  2 +-
 .../profile/impl/ValidateSelectedTrustChain.java   |  2 +-
 ...ultTrustChainMetadataPolicyMergingStrategy.java |  2 +-
 .../DefaultTrustChainSelectionStrategy.java        |  2 +-
 ...aultSubordinateStatementCredentialResolver.java |  2 +-
 .../META-INF/net.shibboleth.idp/postconfig.xml     | 22 ++++++
 .../plugin/oidc/op/oidfed/TrustChainTestUtil.java  | 14 ++--
 .../flow/oidfed/EntityConfigurationFlowTest.java   |  5 +-
 69 files changed, 682 insertions(+), 466 deletions(-)

diff --git a/idp-oidfed-op-api/pom.xml b/idp-oidfed-op-api/pom.xml
index 3fa65ef..77d3005 100644
--- a/idp-oidfed-op-api/pom.xml
+++ b/idp-oidfed-op-api/pom.xml
@@ -96,21 +96,11 @@
             <artifactId>guava</artifactId>
             <scope>provided</scope>
         </dependency>
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-core</artifactId>
-            <scope>provided</scope>
-        </dependency>
         <dependency>
             <groupId>com.nimbusds</groupId>
             <artifactId>oauth2-oidc-sdk</artifactId>
             <scope>provided</scope>
         </dependency>    
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-databind</artifactId>
-            <scope>provided</scope>
-        </dependency>  
         <dependency>
             <groupId>${oidc-common.groupId}</groupId>
             <artifactId>oidc-common-profile-impl</artifactId>
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BaseMetadataPayload.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BaseJWTWrapper.java
similarity index 50%
copy from idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BaseMetadataPayload.java
copy to idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BaseJWTWrapper.java
index eb50156..19fa380 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BaseMetadataPayload.java
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BaseJWTWrapper.java
@@ -14,33 +14,37 @@
 
 package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
+import javax.annotation.Nonnull;
 
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.claim.Metadata;
+import com.nimbusds.jwt.SignedJWT;
+
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
 
 /**
- * Base payload carrying metadata claim.
+ * Base wrapper interface containing {@link SignedJWT} and its parsed payload.
+ *
+ * @param <T> payload format
  */
-public class BaseMetadataPayload extends BaseExpirableSubjectPayload {
+public interface BaseJWTWrapper<T extends BasePayload> {
 
-    /** A JSON object that declares roles that the Entity plays per its Entity Types. */
-    @JsonProperty("metadata") private Metadata metadata;
+    /**
+     * Get the entity statement as JWT.
+     * 
+     * @return JWT
+     */
+    @Nonnull public SignedJWT getJwt();
 
     /**
-     * Get the metadata.
+     * Get the issuer claim of the entity statement.
      * 
-     * @return metadata
+     * @return issuer
      */
-    public Metadata getMetadata() {
-        return metadata;
-    }
+    @Nonnull @NotEmpty public String getIssuer();
 
     /**
-     * Set the metadata.
+     * Get the payload of the entity statement.
      * 
-     * @param data metadata
+     * @return payload
      */
-    public void setMetadata(final Metadata data) {
-        metadata = data;
-    }
+    @Nonnull public T getParsedPayload();
 }
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BasePayload.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BasePayload.java
index a57b31a..d20a39c 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BasePayload.java
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BasePayload.java
@@ -15,93 +15,31 @@
 package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
 
 import java.time.Instant;
-import java.util.HashMap;
 import java.util.Map;
 
-import com.fasterxml.jackson.annotation.JsonAnyGetter;
-import com.fasterxml.jackson.annotation.JsonAnySetter;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.base.MoreObjects;
-
 /**
  * Base payload for claims used within all payloads.
  */
-public class BasePayload {
-
-    /** The Entity Identifier of the Entity Statement. */
-    @JsonProperty("iss") private String issuer;
-
-    /** Time when this statement was issued. */
-    @JsonProperty("iat") private Instant issuedAt;
-
-    /** The map of any other claims not directly mapped. */
-    private final Map<String, Object> customClaims = new HashMap<>();
+public interface BasePayload {
 
     /**
      * Get the issuer.
      * 
      * @return issuer
      */
-    public String getIssuer() {
-        return issuer;
-    }
-
-    /**
-     * Set the issuer.
-     * 
-     * @param iss issuer to set
-     */
-    public void setIssuer(final String iss) {
-        issuer = iss;
-    }
+    public String getIssuer();
 
     /**
      * Get the issuance time.
      * 
      * @return issuance time
      */
-    public Instant getIssuedAt() {
-        return issuedAt;
-    }
-
-    /**
-     * Set the issuance time.
-     * 
-     * @param iat issuance time
-     */
-    public void setIssuedAt(final Instant iat) {
-        issuedAt = iat;
-    }
+    public Instant getIssuedAt();
 
     /**
      * Get the map of custom claims.
      * 
      * @return The map of any other claims not directly mapped.
      */
-    @JsonAnyGetter
-    public Map<String, Object> getCustomClaims() {
-        return customClaims;
-    }
-
-    /**
-     * Add a custom claim to the map of custom claims.
-     * 
-     * @param name The name of the custom claim.
-     * @param value The value of the custom claim.
-     */
-    @JsonAnySetter
-    public void setCustomClaims(final String name, final Object value) {
-        customClaims.put(name, value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override public String toString() {
-        return MoreObjects.toStringHelper(this)
-                .add("iss", issuer)
-                .add("iat", issuedAt)
-                .add("customClaims", customClaims).toString();
-    }
-
+    public Map<String, Object> getCustomClaims();
 }
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityConfiguration.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityConfiguration.java
index 9c10854..4b4e5cd 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityConfiguration.java
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityConfiguration.java
@@ -14,48 +14,11 @@
 
 package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
 
-import javax.annotation.Nonnull;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JavaType;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.nimbusds.jwt.SignedJWT;
-
-import net.shibboleth.shared.logic.ConstraintViolationException;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.EntityConfigurationPayload;
 
 /**
- * A wrapper class extending {@link EntityStatement} with parsed claims related to entity configuration.
+ * A wrapper interface extending {@link EntityStatement} with parsed claims related to entity configuration.
  */
-public class EntityConfiguration extends EntityStatement<EntityConfigurationPayload> {
-
-    /**
-     * Constructor.
-     *
-     * @param signedJwt entity configuration
-     * @param payload entity configuration payload
-     * @throws ConstraintViolationException if the payload syntax/content is not expected
-     */
-    protected EntityConfiguration(@Nonnull final SignedJWT signedJwt,
-            @Nonnull final EntityConfigurationPayload payload) 
-        throws ConstraintViolationException {
-        super(signedJwt, payload);
-    }
+public interface EntityConfiguration extends EntityStatement<EntityConfigurationPayload> {
 
-    /**
-     * Parse an {@link EntityConfiguration} from the given JWT by using the given object mapper.
-     * 
-     * @param jwt entity statement JWT
-     * @param objectMapper object mapper capable of parsing JWT payload
-     * @return entity configuration
-     * @throws JsonProcessingException if the payload could not be parsed
-     */
-    @Nonnull public static EntityConfiguration parse(@Nonnull final SignedJWT jwt,
-            @Nonnull final ObjectMapper objectMapper) throws JsonProcessingException {
-        final JavaType objectType = objectMapper.constructType(EntityConfigurationPayload.class);
-        final EntityConfigurationPayload result =
-                objectMapper.readValue(jwt.getPayload().toString(), objectType);
-        assert result != null;
-        return new EntityConfiguration(jwt, result);
-    }
-    
 }
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityStatement.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityStatement.java
index e3ad358..5438fe8 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityStatement.java
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityStatement.java
@@ -18,39 +18,20 @@ import javax.annotation.Nonnull;
 
 import com.nimbusds.jwt.SignedJWT;
 
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.EntityStatementPayload;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
-import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.logic.ConstraintViolationException;
 
 /**
- * A wrapper class containing the {@link SignedJWT} and parsed claims related to entity statement.
+ * A wrapper inteface containing the {@link SignedJWT} and parsed claims related to entity statement.
  *
  * @param <T> payload format
  */
-public abstract class EntityStatement<T extends EntityStatementPayload> extends AbstractJWTWrapper<T> {
-
-    /**
-     * 
-     * Constructor.
-     *
-     * @param signedJwt entity statement
-     * @param payload entity statement payload
-     * @throws ConstraintViolationException if the payload syntax/content is not expected
-     */
-    protected EntityStatement(@Nonnull final SignedJWT signedJwt, @Nonnull final T payload) 
-        throws ConstraintViolationException {
-        super(signedJwt, payload);
-        Constraint.isNotEmpty(payload.getSubject(), "Subject cannot be empty in the payload");
-    }
+public interface EntityStatement<T extends EntityStatementPayload> extends BaseJWTWrapper<T> {
 
     /**
      * Get the subject claim of the entity statement.
      * 
      * @return subject
      */
-    @Nonnull @NotEmpty public String getSubject() {
-        final String subject = getParsedPayload().getSubject();
-        assert subject != null;
-        return subject;
-    }
+    @Nonnull @NotEmpty public String getSubject();
 }
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponse.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponse.java
index 15fa7a1..f4339b9 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponse.java
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponse.java
@@ -14,47 +14,11 @@
 
 package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
 
-import javax.annotation.Nonnull;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JavaType;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.nimbusds.jwt.SignedJWT;
-
-import net.shibboleth.shared.logic.ConstraintViolationException;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.ResolveEntityResponsePayload;
 
 /**
- * A wrapper class extending {@link EntityStatement} with parsed claims related to resolve entity response.
+ * A wrapper interface extending {@link BaseJWTWrapper} with parsed claims related to resolve entity response.
  */
-public class ResolveEntityResponse extends AbstractJWTWrapper<ResolveEntityResponsePayload> {
-
-    /**
-     * Constructor.
-     *
-     * @param signedJwt entity configuration
-     * @param payload entity configuration payload
-     * @throws ConstraintViolationException if the payload syntax/content is not expected
-     */
-    protected ResolveEntityResponse(@Nonnull final SignedJWT signedJwt,
-            @Nonnull final ResolveEntityResponsePayload payload) 
-        throws ConstraintViolationException {
-        super(signedJwt, payload);
-    }
+public interface ResolveEntityResponse extends BaseJWTWrapper<ResolveEntityResponsePayload> {
 
-    /**
-     * Parse an {@link ResolveEntityResponse} from the given JWT by using the given object mapper.
-     * 
-     * @param jwt entity statement JWT
-     * @param objectMapper object mapper capable of parsing JWT payload
-     * @return entity configuration
-     * @throws JsonProcessingException if the payload could not be parsed
-     */
-    @Nonnull public static ResolveEntityResponse parse(@Nonnull final SignedJWT jwt,
-            @Nonnull final ObjectMapper objectMapper) throws JsonProcessingException {
-        final JavaType objectType = objectMapper.constructType(ResolveEntityResponsePayload.class);
-        final ResolveEntityResponsePayload result = objectMapper.readValue(jwt.getPayload().toString(), objectType);
-        assert result != null;
-        return new ResolveEntityResponse(jwt, result);
-    }
-    
 }
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/SubordinateStatement.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/SubordinateStatement.java
index 1572179..aa01966 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/SubordinateStatement.java
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/SubordinateStatement.java
@@ -14,47 +14,11 @@
 
 package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
 
-import javax.annotation.Nonnull;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JavaType;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.nimbusds.jwt.SignedJWT;
-
-import net.shibboleth.shared.logic.ConstraintViolationException;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.SubordinateStatementPayload;
 
 /**
- * A wrapper class extending {@link EntityStatement} with parsed claims related to subordinate statements.
+ * A wrapper interface extending {@link EntityStatement} with parsed claims related to subordinate statements.
  */
-public class SubordinateStatement extends EntityStatement<SubordinateStatementPayload> {
-
-    /**
-     * Constructor.
-     *
-     * @param signedJwt subordinate statement
-     * @param payload subordinate statement payload
-     * @throws ConstraintViolationException if the payload syntax/content is not expected
-     */
-    protected SubordinateStatement(@Nonnull final SignedJWT signedJwt,
-            @Nonnull final SubordinateStatementPayload payload) 
-        throws ConstraintViolationException {
-        super(signedJwt, payload);
-    }
+public interface SubordinateStatement extends EntityStatement<SubordinateStatementPayload> {
 
-    /**
-     * Parse a {@link SubordinateStatement} from the given JWT by using the given object mapper.
-     * 
-     * @param jwt entity statement JWT
-     * @param objectMapper object mapper capable of parsing JWT payload
-     * @return subordinate statement
-     * @throws JsonProcessingException if the payload could not be parsed
-     */
-    @Nonnull public static SubordinateStatement parse(@Nonnull final SignedJWT jwt,
-            @Nonnull final ObjectMapper objectMapper) throws JsonProcessingException {
-        final JavaType objectType = objectMapper.constructType(SubordinateStatementPayload.class);
-        final SubordinateStatementPayload result =
-                objectMapper.readValue(jwt.getPayload().toString(), objectType);
-        assert result != null;
-        return new SubordinateStatement(jwt, result);
-    }
 }
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMark.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMark.java
index 84f2f47..71858b2 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMark.java
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMark.java
@@ -14,47 +14,11 @@
 
 package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
 
-import javax.annotation.Nonnull;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JavaType;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.nimbusds.jwt.SignedJWT;
-
-import net.shibboleth.shared.logic.ConstraintViolationException;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.TrustMarkPayload;
 
 /**
- * A wrapper class extending {@link EntityStatement} with parsed claims related to trust mark.
+ * A wrapper interface extending {@link BaseJWTWrapper} with parsed claims related to trust mark.
  */
-public class TrustMark extends AbstractJWTWrapper<TrustMarkPayload> {
-
-    /**
-     * Constructor.
-     *
-     * @param signedJwt entity configuration
-     * @param payload entity configuration payload
-     * @throws ConstraintViolationException if the payload syntax/content is not expected
-     */
-    protected TrustMark(@Nonnull final SignedJWT signedJwt,
-            @Nonnull final TrustMarkPayload payload) 
-        throws ConstraintViolationException {
-        super(signedJwt, payload);
-    }
+public interface TrustMark extends BaseJWTWrapper<TrustMarkPayload> {
 
-    /**
-     * Parse an {@link TrustMark} from the given JWT by using the given object mapper.
-     * 
-     * @param jwt entity statement JWT
-     * @param objectMapper object mapper capable of parsing JWT payload
-     * @return entity configuration
-     * @throws JsonProcessingException if the payload could not be parsed
-     */
-    @Nonnull public static TrustMark parse(@Nonnull final SignedJWT jwt,
-            @Nonnull final ObjectMapper objectMapper) throws JsonProcessingException {
-        final JavaType objectType = objectMapper.constructType(TrustMarkPayload.class);
-        final TrustMarkPayload result = objectMapper.readValue(jwt.getPayload().toString(), objectType);
-        assert result != null;
-        return new TrustMark(jwt, result);
-    }
-    
 }
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatus.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatus.java
index a96af2d..56e8b4a 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatus.java
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatus.java
@@ -14,47 +14,11 @@
 
 package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
 
-import javax.annotation.Nonnull;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JavaType;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.nimbusds.jwt.SignedJWT;
-
-import net.shibboleth.shared.logic.ConstraintViolationException;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.TrustMarkStatusPayload;
 
 /**
- * A wrapper class extending {@link EntityStatement} with parsed claims related to trust mark status.
+ * A wrapper interface extending {@link BaseJWTWrapper} with parsed claims related to trust mark status.
  */
-public class TrustMarkStatus extends AbstractJWTWrapper<TrustMarkStatusPayload> {
-
-    /**
-     * Constructor.
-     *
-     * @param signedJwt entity configuration
-     * @param payload entity configuration payload
-     * @throws ConstraintViolationException if the payload syntax/content is not expected
-     */
-    protected TrustMarkStatus(@Nonnull final SignedJWT signedJwt,
-            @Nonnull final TrustMarkStatusPayload payload) 
-        throws ConstraintViolationException {
-        super(signedJwt, payload);
-    }
+public interface TrustMarkStatus extends BaseJWTWrapper<TrustMarkStatusPayload> {
 
-    /**
-     * Parse an {@link TrustMarkStatus} from the given JWT by using the given object mapper.
-     * 
-     * @param jwt entity statement JWT
-     * @param objectMapper object mapper capable of parsing JWT payload
-     * @return entity configuration
-     * @throws JsonProcessingException if the payload could not be parsed
-     */
-    @Nonnull public static TrustMarkStatus parse(@Nonnull final SignedJWT jwt,
-            @Nonnull final ObjectMapper objectMapper) throws JsonProcessingException {
-        final JavaType objectType = objectMapper.constructType(TrustMarkStatusPayload.class);
-        final TrustMarkStatusPayload result = objectMapper.readValue(jwt.getPayload().toString(), objectType);
-        assert result != null;
-        return new TrustMarkStatus(jwt, result);
-    }
-    
 }
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/BaseExpirableSubjectPayload.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/BaseExpirableSubjectPayload.java
new file mode 100644
index 0000000..e39d662
--- /dev/null
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/BaseExpirableSubjectPayload.java
@@ -0,0 +1,39 @@
+/*
+ * 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.metadata.payload;
+
+import java.time.Instant;
+
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.BasePayload;
+
+/**
+ * Base payload carrying subject and expiration.
+ */
+public interface BaseExpirableSubjectPayload extends BasePayload {
+
+    /**
+     * Get the subject.
+     * 
+     * @return subject
+     */
+    public String getSubject();
+
+    /**
+     * Get the expiration time.
+     * 
+     * @return expiration time
+     */
+    public Instant getExpiration();
+}
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BaseMetadataPayload.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/BaseMetadataPayload.java
similarity index 52%
copy from idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BaseMetadataPayload.java
copy to idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/BaseMetadataPayload.java
index eb50156..abf345e 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BaseMetadataPayload.java
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/BaseMetadataPayload.java
@@ -12,35 +12,19 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata;
 
 /**
  * Base payload carrying metadata claim.
  */
-public class BaseMetadataPayload extends BaseExpirableSubjectPayload {
-
-    /** A JSON object that declares roles that the Entity plays per its Entity Types. */
-    @JsonProperty("metadata") private Metadata metadata;
+public interface BaseMetadataPayload extends BaseExpirableSubjectPayload {
 
     /**
      * Get the metadata.
      * 
      * @return metadata
      */
-    public Metadata getMetadata() {
-        return metadata;
-    }
-
-    /**
-     * Set the metadata.
-     * 
-     * @param data metadata
-     */
-    public void setMetadata(final Metadata data) {
-        metadata = data;
-    }
+    public Metadata getMetadata();
 }
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/EntityConfigurationPayload.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/EntityConfigurationPayload.java
new file mode 100644
index 0000000..25cd0a7
--- /dev/null
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/EntityConfigurationPayload.java
@@ -0,0 +1,65 @@
+/*
+ * 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.metadata.payload;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
+/**
+ * Entity Configuration payload claims as defined by the OpenID Federation 1.0 Section 3.2. This class extends the
+ * list of claims defined by {@link EntityStatementPayload} with the claims that MUST or MAY appear in Entity
+ * Configurations but not in Subordinate Statements.
+ */
+public interface EntityConfigurationPayload extends EntityStatementPayload {
+
+    /**
+     * Get the array of strings representing the Entity Identifiers of Immediate Superiors.
+     * 
+     * @return authority hints
+     */
+    @Nullable public List<String> getAuthorityHints();
+
+    /**
+     * Get the array of strings representing the Entity Identifiers of Trust Anchors trusted by the Entity.
+     * 
+     * @return trust anchor hints
+     */
+    @Nullable public List<String> getTrustAnchorHints();
+
+    /**
+     * Get the array of Trust Marks.
+     * 
+     * @return trust marks
+     */
+    @Nullable public List<Map<String, String>> getTrustMarks();
+
+    /**
+     * Get the map of arrays of Entity Identifiers that are trusted to represent the accreditation authority for Trust
+     * Marks.
+     * 
+     * @return trust mark issuers
+     */
+    @Nullable public Map<String, List<String>> getTrustMarkIssuers();
+
+    /**
+     * Get the map of Owners of the Trust Marks.
+     * 
+     * @return trust mark owners
+     */
+    @Nullable public Map<String, Map<String, Object>> getTrustMarkOwners();
+
+}
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/EntityStatementPayload.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/EntityStatementPayload.java
new file mode 100644
index 0000000..d9bc403
--- /dev/null
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/EntityStatementPayload.java
@@ -0,0 +1,41 @@
+/*
+ * 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.metadata.payload;
+
+import java.util.List;
+
+import com.nimbusds.jose.jwk.JWKSet;
+
+/**
+ * Entity Statement payload claims as defined by the OpenID Federation 1.0 Section 3.1. These claims MUST or MAY appear
+ * in both Entity Configurations and Subordinate Statements.
+ */
+public interface EntityStatementPayload extends BaseMetadataPayload {
+
+    /**
+     * Get the JWK set.
+     * 
+     * @return JWK set
+     */
+    public JWKSet getJwks();
+
+    /**
+     * Get the critical claims.
+     * 
+     * @return critical claims
+     */
+    public List<String> getCritical();
+
+}
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/ResolveEntityResponsePayload.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/ResolveEntityResponsePayload.java
new file mode 100644
index 0000000..2ced07b
--- /dev/null
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/ResolveEntityResponsePayload.java
@@ -0,0 +1,41 @@
+/*
+ * 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.metadata.payload;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
+/**
+ * Resolve Entity response payload claims as defined by the OpenID Federation 1.0 Section 8.3.2.
+ */
+public interface ResolveEntityResponsePayload extends BaseMetadataPayload {
+
+    /**
+     * Get the array containing the sequence of Entity Statements that compose the Trust Chain.
+     * 
+     * @return trust chain
+     */
+    @Nullable public List<String> getTrustChain();
+
+    /**
+     * Get the array of Trust Marks.
+     * 
+     * @return trust marks
+     */
+    @Nullable public List<Map<String, String>> getTrustMarks();
+
+}
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/SubordinateStatementPayload.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/SubordinateStatementPayload.java
new file mode 100644
index 0000000..93a4ece
--- /dev/null
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/SubordinateStatementPayload.java
@@ -0,0 +1,59 @@
+/*
+ * 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.metadata.payload;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
+import net.shibboleth.oidc.metadata.policy.MetadataPolicy;
+
+/**
+ * Subordinate Statement payload claims as defined by the OpenID Federation 1.0 Section 3.3. This class extends the
+ * list of claims defined by {@link EntityStatementPayload} with the claims that MUST or MAY appear in Subordinate
+ * Statements but not in Entity Configurations.
+ */
+public interface SubordinateStatementPayload extends EntityStatementPayload {
+
+    /**
+     * Get the map that defines Trust Chain constraints.
+     * 
+     * @return constraints
+     */
+    @Nullable public Map<String, Object> getConstraints();
+
+    /**
+     * Get the map that defines a metadata policy.
+     * 
+     * @return metadata policy
+     */
+    @Nullable public Map<String, Map<String, MetadataPolicy>> getMetadataPolicy();
+
+    /**
+     * Get the list of critical metadata policy operators.
+     * 
+     * @return critical metadata policy operators
+     */
+    @Nullable public List<String> getMetadataPolicyCritical();
+
+    /**
+     * Get the fetch endpoint URL from which the entity statement was issued.
+     * 
+     * @return fetch endpoint URL
+     */
+    @Nullable public String getSourceEndpoint();
+    
+}
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/TrustMarkPayload.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/TrustMarkPayload.java
new file mode 100644
index 0000000..0a0dcbb
--- /dev/null
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/TrustMarkPayload.java
@@ -0,0 +1,51 @@
+/*
+ * 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.metadata.payload;
+
+import javax.annotation.Nullable;
+
+/**
+ * Trust Mark payload claims as defined by the OpenID Federation 1.0 Section 7.1.
+ */
+public interface TrustMarkPayload extends BaseExpirableSubjectPayload {
+
+    /**
+     * Get the identifier of the type of the Trust Mark.
+     * 
+     * @return trust mark type
+     */
+    @Nullable public String getTrustMarkType();
+
+    /**
+     * Get the URL that references a logo for the issued Trust Mark.
+     * 
+     * @return logo URL
+     */
+    @Nullable public String getLogoUri();
+
+    /**
+     * Get the URL referring to human-readable information about the issuance of the Trust Mark.
+     * 
+     * @return reference URL
+     */
+    @Nullable public String getReference();
+
+    /**
+     * Get the Trust Mark delegation JWT.
+     * 
+     * @return delegation JWT
+     */
+    @Nullable public String getDelegation();
+}
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/TrustMarkStatusPayload.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/TrustMarkStatusPayload.java
new file mode 100644
index 0000000..02d787d
--- /dev/null
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/TrustMarkStatusPayload.java
@@ -0,0 +1,40 @@
+/*
+ * 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.metadata.payload;
+
+import javax.annotation.Nullable;
+
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.BasePayload;
+
+/**
+ * Trust Mark Status payload claims as defined by the OpenID Federation 1.0 Section 8.4.2.
+ */
+public interface TrustMarkStatusPayload extends BasePayload {
+
+    /**
+     * Get the Trust Mark.
+     * 
+     * @return trust mark
+     */
+    @Nullable public String getTrustMark();
+
+    /**
+     * Get the status indicator for the Trust Mark.
+     * 
+     * @return status
+     */
+    @Nullable public String getStatus();
+
+}
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/claim/Metadata.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/claim/Metadata.java
new file mode 100644
index 0000000..38468e4
--- /dev/null
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/claim/Metadata.java
@@ -0,0 +1,83 @@
+/*
+ * 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.metadata.payload.claim;
+
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * Metadata claim as defined by the OpenID Federation 1.0 Section 5.
+ */
+public interface Metadata {
+
+    /**
+     * Get the federation entity metadata.
+     * 
+     * @return federation entity metadata
+     */
+    @Nullable public Map<String,Object> getFederationEntityMetadata();
+
+    /**
+     * Get the OpenID Connect Relying Party metadata.
+     * 
+     * @return OIDC RP metadata
+     */
+    @Nullable public Map<String,Object> getOpenidRelyingPartyMetadata();
+
+    /**
+     * Get the OpenID Connect OpenID Provider metadata.
+     * 
+     * @return OIDC OP metadata
+     */
+    @Nullable public Map<String,Object> getOpenidProviderMetadata();
+
+    /**
+     * Get the OAuth Authorization Server metadata.
+     * 
+     * @return OAuth AS metadata
+     */
+    @Nullable public Map<String,Object> getOauthAuthorizationServerMetadata();
+
+    /**
+     * Get the OAuth Client metadata.
+     * 
+     * @return OAuth client metadata
+     */
+    @Nullable public Map<String,Object> getOauthClientMetadata();
+
+    /**
+     * Get the OAuth Protected Resource metadata.
+     * 
+     * @return OAuth protected resource metadata
+     */
+    @Nullable public Map<String,Object> getOauthResourceMetadata();
+
+    /**
+     * Get the map of custom claims.
+     * 
+     * @return The map of any other claims not directly mapped.
+     */
+    public Map<String,Map<String, Object>> getCustomClaims();
+
+    /**
+     * Get all claims (standard and custom) in a map keyed by entity types.
+     * 
+     * @return all claims
+     */
+    @Nonnull public Map<String,Map<String,Object>> getAllClaims();
+
+}
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/context/RelyingPartyTrustChainContext.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/context/RelyingPartyTrustChainContext.java
index 0818958..d7c03da 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/context/RelyingPartyTrustChainContext.java
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/context/RelyingPartyTrustChainContext.java
@@ -26,7 +26,7 @@ import org.opensaml.messaging.context.BaseContext;
 import com.nimbusds.jwt.SignedJWT;
 
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.TrustedRemoteResolverEntity;
 import net.shibboleth.shared.collection.Pair;
 
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/decoding/impl/ExplicitClientRegistrationRequestDecoder.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/decoding/impl/ExplicitClientRegistrationRequestDecoder.java
index 4b6230f..0142a62 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/decoding/impl/ExplicitClientRegistrationRequestDecoder.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/decoding/impl/ExplicitClientRegistrationRequestDecoder.java
@@ -41,6 +41,8 @@ import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.ExplicitClientReg
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityConfiguration;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.SubordinateStatement;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl.EntityConfigurationImpl;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl.SubordinateStatementImpl;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.util.EntityStatementHelper;
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.component.ComponentInitializationException;
@@ -133,10 +135,10 @@ public class ExplicitClientRegistrationRequestDecoder
             final String issuer = jwt.getJWTClaimsSet().getIssuer();
             if (subject != null && subject.equals(issuer)) {
                 assert objectMapper != null;
-                return EntityConfiguration.parse(jwt, objectMapper);
+                return EntityConfigurationImpl.parse(jwt, objectMapper);
             } else {
                 assert objectMapper != null;
-                return SubordinateStatement.parse(jwt, objectMapper);
+                return SubordinateStatementImpl.parse(jwt, objectMapper);
             }
         } catch (final JsonProcessingException | ParseException e) {
             log.warn("Could not parse entity statement", e);
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultTrustChainTrustMarksParsingStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultTrustChainTrustMarksParsingStrategy.java
index 086017f..d598636 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultTrustChainTrustMarksParsingStrategy.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultTrustChainTrustMarksParsingStrategy.java
@@ -29,8 +29,8 @@ import org.slf4j.Logger;
 import com.nimbusds.jwt.JWTClaimsSet;
 import com.nimbusds.jwt.SignedJWT;
 
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityConfigurationPayload;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.EntityConfigurationPayload;
 import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
 import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
 import net.shibboleth.shared.primitive.LoggerFactory;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultTrustChainTrustedTrustMarkIssuersLookupStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultTrustChainTrustedTrustMarkIssuersLookupStrategy.java
index 0f08d85..87267fd 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultTrustChainTrustedTrustMarkIssuersLookupStrategy.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultTrustChainTrustedTrustMarkIssuersLookupStrategy.java
@@ -22,8 +22,8 @@ import java.util.stream.Collectors;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityConfigurationPayload;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.EntityConfigurationPayload;
 import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
 import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultTrustChainTrustedTrustMarkOwnersLookupStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultTrustChainTrustedTrustMarkOwnersLookupStrategy.java
index f1f884a..0fa5eac 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultTrustChainTrustedTrustMarkOwnersLookupStrategy.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultTrustChainTrustedTrustMarkOwnersLookupStrategy.java
@@ -24,8 +24,8 @@ import javax.annotation.concurrent.ThreadSafe;
 
 import org.slf4j.Logger;
 
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityConfigurationPayload;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.EntityConfigurationPayload;
 import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.primitive.LoggerFactory;
 
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/BaseExpirableStatementContainer.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/BaseExpirableStatementContainer.java
index b046f20..12283dc 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/BaseExpirableStatementContainer.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/BaseExpirableStatementContainer.java
@@ -20,8 +20,8 @@ import java.time.Instant;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.AbstractJWTWrapper;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.BaseExpirableSubjectPayload;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.BaseJWTWrapper;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.BaseExpirableSubjectPayload;
 import net.shibboleth.shared.logic.Constraint;
 
 /**
@@ -30,7 +30,7 @@ import net.shibboleth.shared.logic.Constraint;
  * @param <T> wrapped statement
  */
 public abstract class BaseExpirableStatementContainer
-    <T extends AbstractJWTWrapper<? extends BaseExpirableSubjectPayload>>
+    <T extends BaseJWTWrapper<? extends BaseExpirableSubjectPayload>>
     extends BaseExpirableMetadataContainer
     implements Serializable {
 
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/DefaultEntityStatementValidationCriteriaSetLookupFunction.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/DefaultEntityStatementValidationCriteriaSetLookupFunction.java
index 0e09eff..e3f09a6 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/DefaultEntityStatementValidationCriteriaSetLookupFunction.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/DefaultEntityStatementValidationCriteriaSetLookupFunction.java
@@ -22,7 +22,7 @@ import javax.annotation.Nullable;
 
 import org.slf4j.Logger;
 
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.AbstractJWTWrapper;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.BaseJWTWrapper;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityConfiguration;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.SubjectEntityIDCriterion;
 import net.shibboleth.oidc.metadata.cache.MetadataCache;
@@ -73,7 +73,7 @@ public class DefaultEntityStatementValidationCriteriaSetLookupFunction
     @Override @Nullable
     public CriteriaSet apply(@Nullable final BaseExpirableStatementContainer<?> metadataContainer) {
         if (metadataContainer != null && metadataContainer.getStatement() != null) {
-            final AbstractJWTWrapper<?> statement = metadataContainer.getStatement();
+            final BaseJWTWrapper<?> statement = metadataContainer.getStatement();
             assert statement != null;
             final SubjectStatementCriterion subjectCriterion = new SubjectStatementCriterion(statement);
             final IssuerEntityStatementCriterion issuerCriterion = getIssuerCriterion(statement);
@@ -96,7 +96,7 @@ public class DefaultEntityStatementValidationCriteriaSetLookupFunction
      * @return the issuer entity configuration, or null if could not be fetched
      */
     @Nullable protected IssuerEntityStatementCriterion getIssuerCriterion(
-            @Nonnull final AbstractJWTWrapper<?> statement) {
+            @Nonnull final BaseJWTWrapper<?> statement) {
         final String issuer = statement.getIssuer();
         final CriteriaSet criteria = new CriteriaSet(new SubjectEntityIDCriterion(issuer));
         try {
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/SubjectStatementCriterion.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/SubjectStatementCriterion.java
index fabe730..4ed9abf 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/SubjectStatementCriterion.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/SubjectStatementCriterion.java
@@ -18,7 +18,7 @@ import java.util.Objects;
 
 import javax.annotation.Nonnull;
 
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.AbstractJWTWrapper;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.BaseJWTWrapper;
 import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.resolver.Criterion;
 
@@ -28,7 +28,7 @@ import net.shibboleth.shared.resolver.Criterion;
 public class SubjectStatementCriterion implements Criterion {
 
     /** The statement value. */
-    @Nonnull final AbstractJWTWrapper<?> value;
+    @Nonnull final BaseJWTWrapper<?> value;
 
     /**
      * Constructor.
@@ -36,7 +36,7 @@ public class SubjectStatementCriterion implements Criterion {
      * @param statement the statement value, must not be null
      */
     public SubjectStatementCriterion(
-            @Nonnull final AbstractJWTWrapper<?> statement) {
+            @Nonnull final BaseJWTWrapper<?> statement) {
         value = Constraint.isNotNull(statement, "Entity statement cannot be null");
     }
 
@@ -45,7 +45,7 @@ public class SubjectStatementCriterion implements Criterion {
      * 
      * @return the statement value
      */
-    @Nonnull public AbstractJWTWrapper<?> getValue() {
+    @Nonnull public BaseJWTWrapper<?> getValue() {
         return value;
     }
 
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/configuration/DefaultEntityConfigurationFetchingStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/configuration/DefaultEntityConfigurationFetchingStrategy.java
index be74702..9e7e7a6 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/configuration/DefaultEntityConfigurationFetchingStrategy.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/configuration/DefaultEntityConfigurationFetchingStrategy.java
@@ -38,6 +38,7 @@ import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityConfiguration;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.SubjectEntityIDCriterion;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.AbstractFederationEndpointResponseFetchingStrategy;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.RemoteEntityConfigurationContainer;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl.EntityConfigurationImpl;
 import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
 import net.shibboleth.shared.logic.ConstraintViolationException;
 import net.shibboleth.shared.primitive.LoggerFactory;
@@ -110,7 +111,7 @@ public class DefaultEntityConfigurationFetchingStrategy
                     return new RemoteEntityConfigurationContainer(entityId, null, validExpiration, invalidExpiration);
                 }
                 assert objectMapper != null;
-                final EntityConfiguration entityConfiguration = EntityConfiguration.parse(jwt, objectMapper);
+                final EntityConfiguration entityConfiguration = EntityConfigurationImpl.parse(jwt, objectMapper);
                 return new RemoteEntityConfigurationContainer(
                         entityId, entityConfiguration, validExpiration, invalidExpiration);
             } catch (final JsonProcessingException e) {
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/resolver/DefaultResolveEntityTrustChainFetchingStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/resolver/DefaultResolveEntityTrustChainFetchingStrategy.java
index 4e7ab2c..158c824 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/resolver/DefaultResolveEntityTrustChainFetchingStrategy.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/resolver/DefaultResolveEntityTrustChainFetchingStrategy.java
@@ -40,6 +40,7 @@ import com.nimbusds.jwt.SignedJWT;
 
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityResponse;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.AbstractFederationEndpointResponseFetchingStrategy;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl.ResolveEntityResponseImpl;
 import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
 import net.shibboleth.shared.logic.ConstraintViolationException;
 import net.shibboleth.shared.primitive.LoggerFactory;
@@ -115,7 +116,7 @@ public class DefaultResolveEntityTrustChainFetchingStrategy
                             invalidExpiration);
                 }
                 assert objectMapper != null;
-                final ResolveEntityResponse resolveEntity = ResolveEntityResponse.parse(jwt, objectMapper);
+                final ResolveEntityResponse resolveEntity = ResolveEntityResponseImpl.parse(jwt, objectMapper);
                 return new RemoteResolveEntityResponseContainer(
                         identifier, resolveEntity, validExpiration, invalidExpiration);
             } catch (final JsonProcessingException e) {
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/subordinate/DefaultSubordinateStatementFetchingStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/subordinate/DefaultSubordinateStatementFetchingStrategy.java
index 671062a..03b4125 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/subordinate/DefaultSubordinateStatementFetchingStrategy.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/subordinate/DefaultSubordinateStatementFetchingStrategy.java
@@ -45,6 +45,7 @@ import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.AbstractFe
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.RemoteEntityConfigurationContainer;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.RemoteSubordinateStatementContainer;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.SubordinateStatementCacheIdentifier;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl.SubordinateStatementImpl;
 import net.shibboleth.oidc.metadata.cache.MetadataCache;
 import net.shibboleth.oidc.metadata.cache.MetadataCacheException;
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
@@ -177,7 +178,7 @@ public class DefaultSubordinateStatementFetchingStrategy
                     return new RemoteSubordinateStatementContainer(id, null, validExpiration, invalidExpiration);
                 }
                 assert objectMapper != null;
-                final SubordinateStatement statement = SubordinateStatement.parse(jwt, objectMapper);
+                final SubordinateStatement statement = SubordinateStatementImpl.parse(jwt, objectMapper);
                 log.trace("Subordinate statement successfully parsed and stored into the container");
                 return new RemoteSubordinateStatementContainer(id, statement, validExpiration, invalidExpiration);
             } catch (final JsonProcessingException e) {
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustchain/DefaultTrustChainFetchingStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustchain/DefaultTrustChainFetchingStrategy.java
index 5fc493c..c019fd8 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustchain/DefaultTrustChainFetchingStrategy.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustchain/DefaultTrustChainFetchingStrategy.java
@@ -31,7 +31,6 @@ import org.slf4j.Logger;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityConfiguration;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityConfigurationPayload;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.IssuerEntityIDCriterion;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.PreSelectedTrustChainCriterion;
@@ -44,6 +43,7 @@ import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.RemoteTrus
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.SubjectEntityStatementCriterion;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.constraints.FederationPolicyConstraint;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.constraints.FederationPolicyConstraintHelper;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.EntityConfigurationPayload;
 import net.shibboleth.oidc.metadata.cache.MetadataCache;
 import net.shibboleth.oidc.metadata.cache.MetadataCacheException;
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustmark/DefaultTrustMarkFetchingStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustmark/DefaultTrustMarkFetchingStrategy.java
index 427fa81..71d1c84 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustmark/DefaultTrustMarkFetchingStrategy.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustmark/DefaultTrustMarkFetchingStrategy.java
@@ -40,6 +40,7 @@ import com.nimbusds.jwt.SignedJWT;
 
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.TrustMark;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.AbstractFederationEndpointResponseFetchingStrategy;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl.TrustMarkImpl;
 import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
 import net.shibboleth.shared.logic.ConstraintViolationException;
 import net.shibboleth.shared.primitive.LoggerFactory;
@@ -111,7 +112,7 @@ public class DefaultTrustMarkFetchingStrategy
                     return new RemoteTrustMarkContainer(request, null, validExpiration, invalidExpiration);
                 }
                 assert objectMapper != null;
-                final TrustMark trustMark = TrustMark.parse(jwt, objectMapper);
+                final TrustMark trustMark = TrustMarkImpl.parse(jwt, objectMapper);
                 return new RemoteTrustMarkContainer(
                         request, trustMark, validExpiration, invalidExpiration);
             } catch (final JsonProcessingException e) {
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustmark/DefaultTrustMarkStatusFetchingStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustmark/DefaultTrustMarkStatusFetchingStrategy.java
index bb99888..c6b472c 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustmark/DefaultTrustMarkStatusFetchingStrategy.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustmark/DefaultTrustMarkStatusFetchingStrategy.java
@@ -41,6 +41,7 @@ import com.nimbusds.jwt.SignedJWT;
 
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.TrustMarkStatus;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.AbstractFederationEndpointResponseFetchingStrategy;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl.TrustMarkStatusImpl;
 import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
 import net.shibboleth.shared.logic.ConstraintViolationException;
 import net.shibboleth.shared.primitive.LoggerFactory;
@@ -110,7 +111,7 @@ public class DefaultTrustMarkStatusFetchingStrategy
                     return new RemoteTrustMarkStatusContainer(identifier, null, validExpiration, invalidExpiration);
                 }
                 assert objectMapper != null;
-                final TrustMarkStatus trustMarkStatus = TrustMarkStatus.parse(jwt, objectMapper);
+                final TrustMarkStatus trustMarkStatus = TrustMarkStatusImpl.parse(jwt, objectMapper);
                 return new RemoteTrustMarkStatusContainer(
                         identifier, trustMarkStatus, validExpiration, invalidExpiration);
             } catch (final JsonProcessingException e) {
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustmark/DefaultTrustMarkValidationCriteriaSetLookupFunction.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustmark/DefaultTrustMarkValidationCriteriaSetLookupFunction.java
index 24fa782..0d727f3 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustmark/DefaultTrustMarkValidationCriteriaSetLookupFunction.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustmark/DefaultTrustMarkValidationCriteriaSetLookupFunction.java
@@ -22,7 +22,7 @@ import javax.annotation.Nullable;
 
 import org.slf4j.Logger;
 
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.AbstractJWTWrapper;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.BaseJWTWrapper;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.SubjectEntityIDCriterion;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.BaseExpirableStatementContainer;
@@ -80,7 +80,7 @@ public class DefaultTrustMarkValidationCriteriaSetLookupFunction
     @Override @Nullable
     public CriteriaSet apply(@Nullable final BaseExpirableStatementContainer<?> metadataContainer) {
         if (metadataContainer != null && metadataContainer.getStatement() != null) {
-            final AbstractJWTWrapper<?> statement = metadataContainer.getStatement();
+            final BaseJWTWrapper<?> statement = metadataContainer.getStatement();
             assert statement != null;
             final SubjectStatementCriterion subjectCriterion = new SubjectStatementCriterion(statement);
             final IssuerEntityStatementCriterion issuerCriterion = getIssuerCriterion(statement);
@@ -101,7 +101,7 @@ public class DefaultTrustMarkValidationCriteriaSetLookupFunction
      * @return the issuer entity configuration, or null if could not be fetched
      */
     @Nullable protected IssuerEntityStatementCriterion getIssuerCriterion(
-            @Nonnull final AbstractJWTWrapper<?> statement) {
+            @Nonnull final BaseJWTWrapper<?> statement) {
         final String issuer = statement.getIssuer();
         final CriteriaSet criteria = new CriteriaSet(new SubjectEntityIDCriterion(issuer));
         try {
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/FederationPolicyConstraintHelper.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/FederationPolicyConstraintHelper.java
index 65abdc8..9a74b3f 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/FederationPolicyConstraintHelper.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/FederationPolicyConstraintHelper.java
@@ -25,7 +25,7 @@ import org.slf4j.Logger;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.SubordinateStatementPayload;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.SubordinateStatementPayload;
 import net.shibboleth.shared.primitive.LoggerFactory;
 
 /**
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/DefaultAllowedEntityTypesConstraint.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/DefaultAllowedEntityTypesConstraint.java
index 53fdb66..d0a5db1 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/DefaultAllowedEntityTypesConstraint.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/DefaultAllowedEntityTypesConstraint.java
@@ -26,7 +26,7 @@ import org.slf4j.Logger;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata;
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.logic.Constraint;
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/AbstractJWTWrapper.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/AbstractJWTWrapperImpl.java
similarity index 86%
rename from idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/AbstractJWTWrapper.java
rename to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/AbstractJWTWrapperImpl.java
index aea0f17..c3ea00e 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/AbstractJWTWrapper.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/AbstractJWTWrapperImpl.java
@@ -12,13 +12,15 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl;
 
 import javax.annotation.Nonnull;
 
 import com.google.common.base.MoreObjects;
 import com.nimbusds.jwt.SignedJWT;
 
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.BaseJWTWrapper;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.BasePayload;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.logic.ConstraintViolationException;
@@ -28,7 +30,7 @@ import net.shibboleth.shared.logic.ConstraintViolationException;
  *
  * @param <T> payload format
  */
-public abstract class AbstractJWTWrapper<T extends BasePayload> {
+public abstract class AbstractJWTWrapperImpl<T extends BasePayload> implements BaseJWTWrapper<T> {
 
     /** Entity statement as JWT. */
     @Nonnull private final SignedJWT jwt;
@@ -44,7 +46,7 @@ public abstract class AbstractJWTWrapper<T extends BasePayload> {
      * @param payload entity statement payload
      * @throws ConstraintViolationException if the payload syntax/content is not expected
      */
-    protected AbstractJWTWrapper(@Nonnull final SignedJWT signedJwt, @Nonnull final T payload) 
+    protected AbstractJWTWrapperImpl(@Nonnull final SignedJWT signedJwt, @Nonnull final T payload) 
         throws ConstraintViolationException {
         jwt = Constraint.isNotNull(signedJwt, "JWT cannot be null");
         parsedPayload = Constraint.isNotNull(payload, "Entity statement payload cannot be null");
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BasePayload.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/BasePayloadImpl.java
similarity index 93%
copy from idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BasePayload.java
copy to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/BasePayloadImpl.java
index a57b31a..e7470b9 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BasePayload.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/BasePayloadImpl.java
@@ -12,7 +12,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl;
 
 import java.time.Instant;
 import java.util.HashMap;
@@ -23,10 +23,12 @@ import com.fasterxml.jackson.annotation.JsonAnySetter;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.MoreObjects;
 
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.BasePayload;
+
 /**
  * Base payload for claims used within all payloads.
  */
-public class BasePayload {
+public class BasePayloadImpl implements BasePayload {
 
     /** The Entity Identifier of the Entity Statement. */
     @JsonProperty("iss") private String issuer;
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityConfiguration.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/EntityConfigurationImpl.java
similarity index 64%
copy from idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityConfiguration.java
copy to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/EntityConfigurationImpl.java
index 9c10854..d6cb90e 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityConfiguration.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/EntityConfigurationImpl.java
@@ -12,7 +12,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl;
 
 import javax.annotation.Nonnull;
 
@@ -21,12 +21,16 @@ import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.nimbusds.jwt.SignedJWT;
 
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityConfiguration;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.EntityConfigurationPayload;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.impl.EntityConfigurationPayloadImpl;
 import net.shibboleth.shared.logic.ConstraintViolationException;
 
 /**
- * A wrapper class extending {@link EntityStatement} with parsed claims related to entity configuration.
+ * A wrapper class extending {@link EntityStatementImpl} with parsed claims related to entity configuration.
  */
-public class EntityConfiguration extends EntityStatement<EntityConfigurationPayload> {
+public class EntityConfigurationImpl extends EntityStatementImpl<EntityConfigurationPayload>
+    implements EntityConfiguration {
 
     /**
      * Constructor.
@@ -35,27 +39,27 @@ public class EntityConfiguration extends EntityStatement<EntityConfigurationPayl
      * @param payload entity configuration payload
      * @throws ConstraintViolationException if the payload syntax/content is not expected
      */
-    protected EntityConfiguration(@Nonnull final SignedJWT signedJwt,
+    protected EntityConfigurationImpl(@Nonnull final SignedJWT signedJwt,
             @Nonnull final EntityConfigurationPayload payload) 
         throws ConstraintViolationException {
         super(signedJwt, payload);
     }
 
     /**
-     * Parse an {@link EntityConfiguration} from the given JWT by using the given object mapper.
+     * Parse an {@link EntityConfigurationImpl} from the given JWT by using the given object mapper.
      * 
      * @param jwt entity statement JWT
      * @param objectMapper object mapper capable of parsing JWT payload
      * @return entity configuration
      * @throws JsonProcessingException if the payload could not be parsed
      */
-    @Nonnull public static EntityConfiguration parse(@Nonnull final SignedJWT jwt,
+    @Nonnull public static EntityConfigurationImpl parse(@Nonnull final SignedJWT jwt,
             @Nonnull final ObjectMapper objectMapper) throws JsonProcessingException {
-        final JavaType objectType = objectMapper.constructType(EntityConfigurationPayload.class);
-        final EntityConfigurationPayload result =
+        final JavaType objectType = objectMapper.constructType(EntityConfigurationPayloadImpl.class);
+        final EntityConfigurationPayloadImpl result =
                 objectMapper.readValue(jwt.getPayload().toString(), objectType);
         assert result != null;
-        return new EntityConfiguration(jwt, result);
+        return new EntityConfigurationImpl(jwt, result);
     }
     
 }
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityStatement.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/EntityStatementImpl.java
similarity index 77%
copy from idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityStatement.java
copy to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/EntityStatementImpl.java
index e3ad358..07e68b2 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityStatement.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/EntityStatementImpl.java
@@ -12,12 +12,14 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl;
 
 import javax.annotation.Nonnull;
 
 import com.nimbusds.jwt.SignedJWT;
 
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.EntityStatementPayload;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.logic.ConstraintViolationException;
@@ -27,7 +29,8 @@ import net.shibboleth.shared.logic.ConstraintViolationException;
  *
  * @param <T> payload format
  */
-public abstract class EntityStatement<T extends EntityStatementPayload> extends AbstractJWTWrapper<T> {
+public abstract class EntityStatementImpl<T extends EntityStatementPayload> extends AbstractJWTWrapperImpl<T>
+    implements EntityStatement<T> {
 
     /**
      * 
@@ -37,7 +40,7 @@ public abstract class EntityStatement<T extends EntityStatementPayload> extends
      * @param payload entity statement payload
      * @throws ConstraintViolationException if the payload syntax/content is not expected
      */
-    protected EntityStatement(@Nonnull final SignedJWT signedJwt, @Nonnull final T payload) 
+    protected EntityStatementImpl(@Nonnull final SignedJWT signedJwt, @Nonnull final T payload) 
         throws ConstraintViolationException {
         super(signedJwt, payload);
         Constraint.isNotEmpty(payload.getSubject(), "Subject cannot be empty in the payload");
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponse.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/ResolveEntityResponseImpl.java
similarity index 60%
copy from idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponse.java
copy to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/ResolveEntityResponseImpl.java
index 15fa7a1..c29af83 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponse.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/ResolveEntityResponseImpl.java
@@ -12,7 +12,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl;
 
 import javax.annotation.Nonnull;
 
@@ -21,12 +21,16 @@ import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.nimbusds.jwt.SignedJWT;
 
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityResponse;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.ResolveEntityResponsePayload;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.impl.ResolveEntityResponsePayloadImpl;
 import net.shibboleth.shared.logic.ConstraintViolationException;
 
 /**
- * A wrapper class extending {@link EntityStatement} with parsed claims related to resolve entity response.
+ * A wrapper class extending {@link EntityStatementImpl} with parsed claims related to resolve entity response.
  */
-public class ResolveEntityResponse extends AbstractJWTWrapper<ResolveEntityResponsePayload> {
+public class ResolveEntityResponseImpl extends AbstractJWTWrapperImpl<ResolveEntityResponsePayload>
+    implements ResolveEntityResponse {
 
     /**
      * Constructor.
@@ -35,26 +39,26 @@ public class ResolveEntityResponse extends AbstractJWTWrapper<ResolveEntityRespo
      * @param payload entity configuration payload
      * @throws ConstraintViolationException if the payload syntax/content is not expected
      */
-    protected ResolveEntityResponse(@Nonnull final SignedJWT signedJwt,
+    protected ResolveEntityResponseImpl(@Nonnull final SignedJWT signedJwt,
             @Nonnull final ResolveEntityResponsePayload payload) 
         throws ConstraintViolationException {
         super(signedJwt, payload);
     }
 
     /**
-     * Parse an {@link ResolveEntityResponse} from the given JWT by using the given object mapper.
+     * Parse an {@link ResolveEntityResponseImpl} from the given JWT by using the given object mapper.
      * 
      * @param jwt entity statement JWT
      * @param objectMapper object mapper capable of parsing JWT payload
      * @return entity configuration
      * @throws JsonProcessingException if the payload could not be parsed
      */
-    @Nonnull public static ResolveEntityResponse parse(@Nonnull final SignedJWT jwt,
+    @Nonnull public static ResolveEntityResponseImpl parse(@Nonnull final SignedJWT jwt,
             @Nonnull final ObjectMapper objectMapper) throws JsonProcessingException {
-        final JavaType objectType = objectMapper.constructType(ResolveEntityResponsePayload.class);
-        final ResolveEntityResponsePayload result = objectMapper.readValue(jwt.getPayload().toString(), objectType);
+        final JavaType objectType = objectMapper.constructType(ResolveEntityResponsePayloadImpl.class);
+        final ResolveEntityResponsePayloadImpl result = objectMapper.readValue(jwt.getPayload().toString(), objectType);
         assert result != null;
-        return new ResolveEntityResponse(jwt, result);
+        return new ResolveEntityResponseImpl(jwt, result);
     }
     
 }
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/SubordinateStatement.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/SubordinateStatementImpl.java
similarity index 63%
copy from idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/SubordinateStatement.java
copy to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/SubordinateStatementImpl.java
index 1572179..18ea446 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/SubordinateStatement.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/SubordinateStatementImpl.java
@@ -12,7 +12,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl;
 
 import javax.annotation.Nonnull;
 
@@ -21,12 +21,16 @@ import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.nimbusds.jwt.SignedJWT;
 
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.SubordinateStatement;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.SubordinateStatementPayload;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.impl.SubordinateStatementPayloadImpl;
 import net.shibboleth.shared.logic.ConstraintViolationException;
 
 /**
- * A wrapper class extending {@link EntityStatement} with parsed claims related to subordinate statements.
+ * A wrapper class extending {@link EntityStatementImpl} with parsed claims related to subordinate statements.
  */
-public class SubordinateStatement extends EntityStatement<SubordinateStatementPayload> {
+public class SubordinateStatementImpl extends EntityStatementImpl<SubordinateStatementPayload> 
+    implements SubordinateStatement {
 
     /**
      * Constructor.
@@ -35,26 +39,26 @@ public class SubordinateStatement extends EntityStatement<SubordinateStatementPa
      * @param payload subordinate statement payload
      * @throws ConstraintViolationException if the payload syntax/content is not expected
      */
-    protected SubordinateStatement(@Nonnull final SignedJWT signedJwt,
+    protected SubordinateStatementImpl(@Nonnull final SignedJWT signedJwt,
             @Nonnull final SubordinateStatementPayload payload) 
         throws ConstraintViolationException {
         super(signedJwt, payload);
     }
 
     /**
-     * Parse a {@link SubordinateStatement} from the given JWT by using the given object mapper.
+     * Parse a {@link SubordinateStatementImpl} from the given JWT by using the given object mapper.
      * 
      * @param jwt entity statement JWT
      * @param objectMapper object mapper capable of parsing JWT payload
      * @return subordinate statement
      * @throws JsonProcessingException if the payload could not be parsed
      */
-    @Nonnull public static SubordinateStatement parse(@Nonnull final SignedJWT jwt,
+    @Nonnull public static SubordinateStatementImpl parse(@Nonnull final SignedJWT jwt,
             @Nonnull final ObjectMapper objectMapper) throws JsonProcessingException {
-        final JavaType objectType = objectMapper.constructType(SubordinateStatementPayload.class);
-        final SubordinateStatementPayload result =
+        final JavaType objectType = objectMapper.constructType(SubordinateStatementPayloadImpl.class);
+        final SubordinateStatementPayloadImpl result =
                 objectMapper.readValue(jwt.getPayload().toString(), objectType);
         assert result != null;
-        return new SubordinateStatement(jwt, result);
+        return new SubordinateStatementImpl(jwt, result);
     }
 }
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMark.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/TrustMarkImpl.java
similarity index 64%
copy from idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMark.java
copy to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/TrustMarkImpl.java
index 84f2f47..43099ed 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMark.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/TrustMarkImpl.java
@@ -12,7 +12,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl;
 
 import javax.annotation.Nonnull;
 
@@ -21,12 +21,15 @@ import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.nimbusds.jwt.SignedJWT;
 
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.TrustMark;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.TrustMarkPayload;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.impl.TrustMarkPayloadImpl;
 import net.shibboleth.shared.logic.ConstraintViolationException;
 
 /**
- * A wrapper class extending {@link EntityStatement} with parsed claims related to trust mark.
+ * A wrapper class extending {@link EntityStatementImpl} with parsed claims related to trust mark.
  */
-public class TrustMark extends AbstractJWTWrapper<TrustMarkPayload> {
+public class TrustMarkImpl extends AbstractJWTWrapperImpl<TrustMarkPayload> implements TrustMark {
 
     /**
      * Constructor.
@@ -35,26 +38,26 @@ public class TrustMark extends AbstractJWTWrapper<TrustMarkPayload> {
      * @param payload entity configuration payload
      * @throws ConstraintViolationException if the payload syntax/content is not expected
      */
-    protected TrustMark(@Nonnull final SignedJWT signedJwt,
+    protected TrustMarkImpl(@Nonnull final SignedJWT signedJwt,
             @Nonnull final TrustMarkPayload payload) 
         throws ConstraintViolationException {
         super(signedJwt, payload);
     }
 
     /**
-     * Parse an {@link TrustMark} from the given JWT by using the given object mapper.
+     * Parse an {@link TrustMarkImpl} from the given JWT by using the given object mapper.
      * 
      * @param jwt entity statement JWT
      * @param objectMapper object mapper capable of parsing JWT payload
      * @return entity configuration
      * @throws JsonProcessingException if the payload could not be parsed
      */
-    @Nonnull public static TrustMark parse(@Nonnull final SignedJWT jwt,
+    @Nonnull public static TrustMarkImpl parse(@Nonnull final SignedJWT jwt,
             @Nonnull final ObjectMapper objectMapper) throws JsonProcessingException {
-        final JavaType objectType = objectMapper.constructType(TrustMarkPayload.class);
-        final TrustMarkPayload result = objectMapper.readValue(jwt.getPayload().toString(), objectType);
+        final JavaType objectType = objectMapper.constructType(TrustMarkPayloadImpl.class);
+        final TrustMarkPayloadImpl result = objectMapper.readValue(jwt.getPayload().toString(), objectType);
         assert result != null;
-        return new TrustMark(jwt, result);
+        return new TrustMarkImpl(jwt, result);
     }
     
 }
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatus.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/TrustMarkStatusImpl.java
similarity index 62%
copy from idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatus.java
copy to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/TrustMarkStatusImpl.java
index a96af2d..5d8191a 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatus.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/impl/TrustMarkStatusImpl.java
@@ -12,7 +12,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl;
 
 import javax.annotation.Nonnull;
 
@@ -21,12 +21,16 @@ import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.nimbusds.jwt.SignedJWT;
 
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.TrustMarkStatus;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.TrustMarkStatusPayload;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.impl.TrustMarkStatusPayloadImpl;
 import net.shibboleth.shared.logic.ConstraintViolationException;
 
 /**
- * A wrapper class extending {@link EntityStatement} with parsed claims related to trust mark status.
+ * A wrapper class extending {@link EntityStatementImpl} with parsed claims related to trust mark status.
  */
-public class TrustMarkStatus extends AbstractJWTWrapper<TrustMarkStatusPayload> {
+public class TrustMarkStatusImpl extends AbstractJWTWrapperImpl<TrustMarkStatusPayload>
+    implements TrustMarkStatus {
 
     /**
      * Constructor.
@@ -35,26 +39,26 @@ public class TrustMarkStatus extends AbstractJWTWrapper<TrustMarkStatusPayload>
      * @param payload entity configuration payload
      * @throws ConstraintViolationException if the payload syntax/content is not expected
      */
-    protected TrustMarkStatus(@Nonnull final SignedJWT signedJwt,
+    protected TrustMarkStatusImpl(@Nonnull final SignedJWT signedJwt,
             @Nonnull final TrustMarkStatusPayload payload) 
         throws ConstraintViolationException {
         super(signedJwt, payload);
     }
 
     /**
-     * Parse an {@link TrustMarkStatus} from the given JWT by using the given object mapper.
+     * Parse an {@link TrustMarkStatusImpl} from the given JWT by using the given object mapper.
      * 
      * @param jwt entity statement JWT
      * @param objectMapper object mapper capable of parsing JWT payload
      * @return entity configuration
      * @throws JsonProcessingException if the payload could not be parsed
      */
-    @Nonnull public static TrustMarkStatus parse(@Nonnull final SignedJWT jwt,
+    @Nonnull public static TrustMarkStatusImpl parse(@Nonnull final SignedJWT jwt,
             @Nonnull final ObjectMapper objectMapper) throws JsonProcessingException {
-        final JavaType objectType = objectMapper.constructType(TrustMarkStatusPayload.class);
-        final TrustMarkStatusPayload result = objectMapper.readValue(jwt.getPayload().toString(), objectType);
+        final JavaType objectType = objectMapper.constructType(TrustMarkStatusPayloadImpl.class);
+        final TrustMarkStatusPayloadImpl result = objectMapper.readValue(jwt.getPayload().toString(), objectType);
         assert result != null;
-        return new TrustMarkStatus(jwt, result);
+        return new TrustMarkStatusImpl(jwt, result);
     }
     
 }
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/claim/Metadata.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/claim/impl/MetadataImpl.java
similarity index 96%
rename from idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/claim/Metadata.java
rename to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/claim/impl/MetadataImpl.java
index 01977f1..74b08d8 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/claim/Metadata.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/claim/impl/MetadataImpl.java
@@ -12,7 +12,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.claim;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.impl;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -25,12 +25,13 @@ import com.fasterxml.jackson.annotation.JsonAnySetter;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.MoreObjects;
 
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata;
 import net.shibboleth.shared.collection.CollectionSupport;
 
 /**
  * Metadata claim as defined by the OpenID Federation 1.0 Section 5.
  */
-public class Metadata {
+public class MetadataImpl implements Metadata {
 
     /** Federation entity metadata. */
     @JsonProperty("federation_entity") private Map<String,Object> federationEntityMetadata;
@@ -56,7 +57,7 @@ public class Metadata {
     /**
      * Constructor.
      */
-    public Metadata() {
+    public MetadataImpl() {
         // no op
     }
 
@@ -65,7 +66,7 @@ public class Metadata {
      *
      * @param allClaims claims used for populating this object
      */
-    public Metadata(@Nonnull final Map<String, Map<String, Object>> allClaims) {
+    public MetadataImpl(@Nonnull final Map<String, Map<String, Object>> allClaims) {
         final Map<String,Map<String,Object>> input = new HashMap<>(allClaims);
         if (allClaims.containsKey("federation_entity")) {
             federationEntityMetadata = allClaims.get("federation_entity");
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BaseExpirableSubjectPayload.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/BaseExpirableSubjectPayloadImpl.java
similarity index 84%
rename from idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BaseExpirableSubjectPayload.java
rename to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/BaseExpirableSubjectPayloadImpl.java
index d122489..b72314d 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BaseExpirableSubjectPayload.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/BaseExpirableSubjectPayloadImpl.java
@@ -12,17 +12,20 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.impl;
 
 import java.time.Instant;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.MoreObjects;
 
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl.BasePayloadImpl;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.BaseExpirableSubjectPayload;
+
 /**
  * Base payload carrying subject and expiration.
  */
-public class BaseExpirableSubjectPayload extends BasePayload {
+public class BaseExpirableSubjectPayloadImpl extends BasePayloadImpl implements BaseExpirableSubjectPayload {
 
     /** The Entity Identifier of the subject. */
     @JsonProperty("sub") private String subject;
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BaseMetadataPayload.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/BaseMetadataPayloadImpl.java
similarity index 76%
rename from idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BaseMetadataPayload.java
rename to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/BaseMetadataPayloadImpl.java
index eb50156..f489306 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/BaseMetadataPayload.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/BaseMetadataPayloadImpl.java
@@ -12,16 +12,17 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.impl;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.BaseMetadataPayload;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata;
 
 /**
  * Base payload carrying metadata claim.
  */
-public class BaseMetadataPayload extends BaseExpirableSubjectPayload {
+public class BaseMetadataPayloadImpl extends BaseExpirableSubjectPayloadImpl implements BaseMetadataPayload {
 
     /** A JSON object that declares roles that the Entity plays per its Entity Types. */
     @JsonProperty("metadata") private Metadata metadata;
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityConfigurationPayload.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/EntityConfigurationPayloadImpl.java
similarity index 92%
rename from idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityConfigurationPayload.java
rename to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/EntityConfigurationPayloadImpl.java
index 178df20..af5ca0e 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityConfigurationPayload.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/EntityConfigurationPayloadImpl.java
@@ -12,7 +12,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.impl;
 
 import java.util.List;
 import java.util.Map;
@@ -22,12 +22,14 @@ import javax.annotation.Nullable;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.MoreObjects;
 
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.EntityConfigurationPayload;
+
 /**
  * Entity Configuration payload claims as defined by the OpenID Federation 1.0 Section 3.2. This class extends the
- * list of claims defined by {@link EntityStatementPayload} with the claims that MUST or MAY appear in Entity
+ * list of claims defined by {@link EntityStatementPayloadImpl} with the claims that MUST or MAY appear in Entity
  * Configurations but not in Subordinate Statements.
  */
-public class EntityConfigurationPayload extends EntityStatementPayload {
+public class EntityConfigurationPayloadImpl extends EntityStatementPayloadImpl implements EntityConfigurationPayload {
 
     /** An array of strings representing the Entity Identifiers of Immediate Superiors. */
     @JsonProperty("authority_hints") private List<String> authorityHints;
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityStatementPayload.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/EntityStatementPayloadImpl.java
similarity index 89%
rename from idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityStatementPayload.java
rename to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/EntityStatementPayloadImpl.java
index 0c40482..56cef83 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityStatementPayload.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/EntityStatementPayloadImpl.java
@@ -12,7 +12,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.impl;
 
 import java.util.List;
 
@@ -20,11 +20,13 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.MoreObjects;
 import com.nimbusds.jose.jwk.JWKSet;
 
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.EntityStatementPayload;
+
 /**
  * Entity Statement payload claims as defined by the OpenID Federation 1.0 Section 3.1. These claims MUST or MAY appear
  * in both Entity Configurations and Subordinate Statements.
  */
-public class EntityStatementPayload extends BaseMetadataPayload {
+public class EntityStatementPayloadImpl extends BaseMetadataPayloadImpl implements EntityStatementPayload {
 
     /** A JSON Web Key Set representing the public part of the subject's Federation Entity signing keys. */
     @JsonProperty("jwks") private JWKSet jwkSet;
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponsePayload.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/ResolveEntityResponsePayloadImpl.java
similarity index 89%
rename from idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponsePayload.java
rename to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/ResolveEntityResponsePayloadImpl.java
index dec3bea..64f77ac 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponsePayload.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/ResolveEntityResponsePayloadImpl.java
@@ -12,7 +12,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.impl;
 
 import java.util.List;
 import java.util.Map;
@@ -22,10 +22,12 @@ import javax.annotation.Nullable;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.MoreObjects;
 
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.ResolveEntityResponsePayload;
+
 /**
  * Resolve Entity response payload claims as defined by the OpenID Federation 1.0 Section 8.3.2.
  */
-public class ResolveEntityResponsePayload extends BaseMetadataPayload {
+public class ResolveEntityResponsePayloadImpl extends BaseMetadataPayloadImpl implements ResolveEntityResponsePayload {
 
     /** An array containing the sequence of Entity Statements that compose the Trust Chain. */
     @JsonProperty("trust_chain") private List<String> trustChain;
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/SubordinateStatementPayload.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/SubordinateStatementPayloadImpl.java
similarity index 91%
rename from idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/SubordinateStatementPayload.java
rename to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/SubordinateStatementPayloadImpl.java
index cbdae5a..972bb25 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/SubordinateStatementPayload.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/SubordinateStatementPayloadImpl.java
@@ -12,7 +12,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.impl;
 
 import java.util.List;
 import java.util.Map;
@@ -22,14 +22,16 @@ import javax.annotation.Nullable;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.MoreObjects;
 
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.SubordinateStatementPayload;
 import net.shibboleth.oidc.metadata.policy.MetadataPolicy;
 
 /**
  * Subordinate Statement payload claims as defined by the OpenID Federation 1.0 Section 3.3. This class extends the
- * list of claims defined by {@link EntityStatementPayload} with the claims that MUST or MAY appear in Subordinate
+ * list of claims defined by {@link EntityStatementPayloadImpl} with the claims that MUST or MAY appear in Subordinate
  * Statements but not in Entity Configurations.
  */
-public class SubordinateStatementPayload extends EntityStatementPayload {
+public class SubordinateStatementPayloadImpl extends EntityStatementPayloadImpl
+    implements SubordinateStatementPayload {
 
     /** A map that defines Trust Chain constraints. */
     @JsonProperty("constraints") private Map<String, Object> constraints;
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkPayload.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/TrustMarkPayloadImpl.java
similarity index 93%
rename from idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkPayload.java
rename to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/TrustMarkPayloadImpl.java
index 17937b1..69c5b1c 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkPayload.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/TrustMarkPayloadImpl.java
@@ -12,17 +12,19 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.impl;
 
 import javax.annotation.Nullable;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.MoreObjects;
 
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.TrustMarkPayload;
+
 /**
  * Trust Mark payload claims as defined by the OpenID Federation 1.0 Section 7.1.
  */
-public class TrustMarkPayload extends BaseExpirableSubjectPayload {
+public class TrustMarkPayloadImpl extends BaseExpirableSubjectPayloadImpl implements TrustMarkPayload {
 
     /** An identifier of the type of the Trust Mark. */
     @JsonProperty("trust_mark_type") private String trustMarkType;
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatusPayload.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/TrustMarkStatusPayloadImpl.java
similarity index 85%
rename from idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatusPayload.java
rename to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/TrustMarkStatusPayloadImpl.java
index ad6bbb5..51fc480 100644
--- a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatusPayload.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/payload/impl/TrustMarkStatusPayloadImpl.java
@@ -12,17 +12,20 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.impl;
 
 import javax.annotation.Nullable;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.MoreObjects;
 
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl.BasePayloadImpl;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.TrustMarkStatusPayload;
+
 /**
  * Trust Mark Status payload claims as defined by the OpenID Federation 1.0 Section 8.4.2.
  */
-public class TrustMarkStatusPayload extends BasePayload {
+public class TrustMarkStatusPayloadImpl extends BasePayloadImpl implements TrustMarkStatusPayload {
 
     /** A Trust Mark. */
     @JsonProperty("trust_mark") private String trustMark;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/AbstractTrustChainResolutionAction.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/AbstractTrustChainResolutionAction.java
index 148284f..849b731 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/AbstractTrustChainResolutionAction.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/AbstractTrustChainResolutionAction.java
@@ -32,7 +32,8 @@ import org.slf4j.Logger;
 
 import net.minidev.json.JSONObject;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.impl.MetadataImpl;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.policy.FederationMetadataPolicyHelper;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.context.RelyingPartyTrustChainContext;
 import net.shibboleth.idp.profile.AbstractProfileAction;
@@ -276,7 +277,7 @@ public class AbstractTrustChainResolutionAction extends AbstractProfileAction {
                             chain.get(0).getSubject(), entityType);
                 }
             }
-            policyCompliantChains.add(new Pair<>(chain, new Metadata(verifiedMetadata)));
+            policyCompliantChains.add(new Pair<>(chain, new MetadataImpl(verifiedMetadata)));
             log.debug("{} Policy-enforced metadata {}", getLogPrefix(), verifiedMetadata);
             return null;
         }
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/AddExtensionsToClientInformation.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/AddExtensionsToClientInformation.java
index e221e58..2bb5a9f 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/AddExtensionsToClientInformation.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/AddExtensionsToClientInformation.java
@@ -33,7 +33,7 @@ import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
 
 import net.shibboleth.idp.plugin.oidc.op.messaging.context.OIDCClientRegistrationResponseContext;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.context.RelyingPartyTrustChainContext;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.support.ClientInformationExtensionSupport;
 import net.shibboleth.idp.profile.AbstractProfileAction;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/BuildResolveEntityResponse.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/BuildResolveEntityResponse.java
index 8fa53f3..5e42d49 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/BuildResolveEntityResponse.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/BuildResolveEntityResponse.java
@@ -38,7 +38,7 @@ import com.nimbusds.jwt.JWTClaimsSet;
 import com.nimbusds.jwt.SignedJWT;
 
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.context.RelyingPartyTrustChainContext;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.navigate.DefaultEntityTypesLookupFunction;
 import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/CallResolveEntityApi.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/CallResolveEntityApi.java
index 885f78e..7395973 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/CallResolveEntityApi.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/CallResolveEntityApi.java
@@ -48,8 +48,6 @@ import net.shibboleth.idp.authn.AuthnEventIds;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityConfiguration;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityResponse;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityResponsePayload;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.SubordinateStatement;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.ResponseContainerExpirationCriterion;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.SubjectEntityIDCriterion;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.RemoteEntityConfigurationContainer;
@@ -57,7 +55,10 @@ import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.SubjectEnt
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.resolver.RemoteResolveEntityCacheContainerIdentifier;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.resolver.RemoteResolveEntityCacheIdentifierCriterion;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.resolver.RemoteResolveEntityResponseContainer;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl.EntityConfigurationImpl;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl.SubordinateStatementImpl;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.ResolveEntityResponsePayload;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.TrustedRemoteResolverEntity;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.context.RelyingPartyTrustChainContext;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.navigate.DefaultPreSelectedTrustChainIDsLookupStrategy;
@@ -429,9 +430,10 @@ public class CallResolveEntityApi extends AbstractProfileAction {
                             trustedEntity);
                     continue;
                 }
-                final List<EntityStatement<?>> chain = rawTrustChain.stream()
+                final List<EntityStatement<?>> chain = new ArrayList<>();
+                rawTrustChain.stream()
                         .filter(Objects::nonNull)
-                        .map(entry -> {
+                        .forEach(entry -> {
                             try {
                                 final SignedJWT jwt = SignedJWT.parse(entry);
                                 assert jwt != null;
@@ -440,18 +442,15 @@ public class CallResolveEntityApi extends AbstractProfileAction {
                                 final String issuer = jwt.getJWTClaimsSet().getIssuer();
                                 if (subject != null && subject.equals(issuer)) {
                                     assert objectMapper != null;
-                                    return EntityConfiguration.parse(jwt, objectMapper);
+                                    chain.add(EntityConfigurationImpl.parse(jwt, objectMapper));
                                 } else {
                                     assert objectMapper != null;
-                                    return SubordinateStatement.parse(jwt, objectMapper);
+                                    chain.add(SubordinateStatementImpl.parse(jwt, objectMapper));
                                 }
                             } catch (final JsonProcessingException | ParseException e) {
                                 log.warn("Could not parse the trust chain into list of entity statements", e);
-                                return null;
                             }
-                        })
-                        .filter(Objects::nonNull)
-                        .toList();
+                        });
                 if (!preSelectedChain.isEmpty() && !preSelectedChain.equals(trustChainIDsLookupStrategy.apply(chain))) {
                     log.debug("{} Ignored resolved trust chain that doesn't match with preselected chain",
                             getLogPrefix());
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ResolveTrustChains.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ResolveTrustChains.java
index 8446eec..2a0e538 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ResolveTrustChains.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ResolveTrustChains.java
@@ -37,7 +37,7 @@ import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.SubjectEntityIDCriterion;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.RemoteTrustChainsContainer;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.SubjectEntityStatementCriterion;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.context.RelyingPartyTrustChainContext;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.navigate.DefaultPreSelectedTrustChainIDsLookupStrategy;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.navigate.DefaultTrustChainIDsLookupStrategy;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ResolveTrustMarks.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ResolveTrustMarks.java
index f655fb4..43bc044 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ResolveTrustMarks.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ResolveTrustMarks.java
@@ -44,7 +44,7 @@ import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.SubjectEntityIDCr
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.TrustMarkOwnersCriterion;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.RemoteTrustChainsContainer;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.SubjectEntityStatementCriterion;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.context.RelyingPartyTrustChainContext;
 import net.shibboleth.idp.profile.AbstractProfileAction;
 import net.shibboleth.oidc.jwt.claims.ClaimsValidator;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/SelectTrustChain.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/SelectTrustChain.java
index 5b0520b..f831080 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/SelectTrustChain.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/SelectTrustChain.java
@@ -27,7 +27,7 @@ import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
 import org.slf4j.Logger;
 
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.context.RelyingPartyTrustChainContext;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.navigate.DefaultTrustChainSelectionStrategy;
 import net.shibboleth.idp.profile.AbstractProfileAction;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/StoreAutomaticRegistration.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/StoreAutomaticRegistration.java
index 9a35faa..2a491a4 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/StoreAutomaticRegistration.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/StoreAutomaticRegistration.java
@@ -32,7 +32,7 @@ import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
 import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata;
 
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.context.RelyingPartyTrustChainContext;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.navigate.DefaultSelectedTrustChainMetadataLookupStrategy;
 import net.shibboleth.idp.profile.AbstractProfileAction;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateAutomaticRegistrationProfileConfiguration.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateAutomaticRegistrationProfileConfiguration.java
index 412caf9..2ba30d2 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateAutomaticRegistrationProfileConfiguration.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateAutomaticRegistrationProfileConfiguration.java
@@ -34,7 +34,8 @@ import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
 import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata;
 
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.impl.MetadataImpl;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.config.navigate.LocalMetadataPolicyLookupFunction;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.config.navigate.MandatoryTrustMarksLookupFunction;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.context.RelyingPartyTrustChainContext;
@@ -214,7 +215,7 @@ public class ValidateAutomaticRegistrationProfileConfiguration extends AbstractP
                 ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
                 return;
             }
-            final Metadata selectedMetadata = new Metadata();
+            final MetadataImpl selectedMetadata = new MetadataImpl();
             selectedMetadata.setOpenidRelyingPartyMetadata(clientInformation.toJSONObject());
             selectedTrustChain.setSecond(selectedMetadata);
         } else {
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateProvidedTrustChain.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateProvidedTrustChain.java
index 5b2a8e6..b368c1c 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateProvidedTrustChain.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateProvidedTrustChain.java
@@ -26,7 +26,7 @@ import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
 
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.context.RelyingPartyTrustChainContext;
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateSelectedTrustChain.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateSelectedTrustChain.java
index 0460ff0..841a275 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateSelectedTrustChain.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateSelectedTrustChain.java
@@ -29,7 +29,7 @@ import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.ResolveEntityRequ
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.SubjectEntityIDCriterion;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.RemoteEntityConfigurationContainer;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.context.RelyingPartyTrustChainContext;
 import net.shibboleth.idp.profile.AbstractProfileAction;
 import net.shibboleth.oidc.metadata.cache.MetadataCache;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/navigate/DefaultTrustChainMetadataPolicyMergingStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/navigate/DefaultTrustChainMetadataPolicyMergingStrategy.java
index 019ddc1..4c968d8 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/navigate/DefaultTrustChainMetadataPolicyMergingStrategy.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/navigate/DefaultTrustChainMetadataPolicyMergingStrategy.java
@@ -24,7 +24,7 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.SubordinateStatementPayload;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.SubordinateStatementPayload;
 import net.shibboleth.oidc.metadata.policy.MetadataPolicy;
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/navigate/DefaultTrustChainSelectionStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/navigate/DefaultTrustChainSelectionStrategy.java
index e893f8a..6e94022 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/navigate/DefaultTrustChainSelectionStrategy.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/navigate/DefaultTrustChainSelectionStrategy.java
@@ -22,7 +22,7 @@ import javax.annotation.Nullable;
 import org.slf4j.Logger;
 
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.context.RelyingPartyTrustChainContext;
 import net.shibboleth.shared.collection.Pair;
 import net.shibboleth.shared.primitive.LoggerFactory;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/security/credential/DefaultSubordinateStatementCredentialResolver.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/security/credential/DefaultSubordinateStatementCredentialResolver.java
index 1fe9096..feb3bfb 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/security/credential/DefaultSubordinateStatementCredentialResolver.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/security/credential/DefaultSubordinateStatementCredentialResolver.java
@@ -24,11 +24,11 @@ import org.slf4j.Logger;
 
 import com.nimbusds.jose.jwk.JWKSet;
 
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.BaseExpirableSubjectPayload;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.IssuerEntityStatementCriterion;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.SubjectEntityStatementCriterion;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.SubjectStatementCriterion;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.BaseExpirableSubjectPayload;
 import net.shibboleth.oidc.security.credential.impl.BasicJOSEObjectCredentialResolver;
 import net.shibboleth.shared.primitive.LoggerFactory;
 import net.shibboleth.shared.resolver.CriteriaSet;
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 1c75a39..062e1d4 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
@@ -630,6 +630,7 @@
 
     <bean id="shibboleth.oidfed.JWTPayloadJSONObjectMapper" parent="shibboleth.oidc.JSONObjectMapper" />
     <bean id="shibboleth.oidfed.policy.JSONSimpleModule" class="com.fasterxml.jackson.databind.module.SimpleModule"/>
+    <bean id="shibboleth.oidfed.JacksonSimpleTypeResolver" class="com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver"/>
 
     <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
         <property name="targetObject" ref="shibboleth.oidfed.policy.JSONSimpleModule" />
@@ -665,6 +666,27 @@
         </property>
     </bean>
 
+    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
+        <property name="targetObject" ref="shibboleth.oidfed.JacksonSimpleTypeResolver" />
+        <property name="targetMethod" value="addMapping" />
+        <property name="arguments">
+            <list>
+                <value>#{ T(net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata)}</value>
+                <value>#{ T(net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.impl.MetadataImpl)}</value>
+            </list>
+        </property>
+    </bean>
+
+    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
+        <property name="targetObject" ref="shibboleth.oidfed.policy.JSONSimpleModule" />
+        <property name="targetMethod" value="setAbstractTypes" />
+        <property name="arguments">
+            <list>
+                <ref bean="shibboleth.oidfed.JacksonSimpleTypeResolver" />
+            </list>
+        </property>
+    </bean>
+
     <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
         <property name="targetObject" ref="shibboleth.oidfed.JWTPayloadJSONObjectMapper" />
         <property name="targetMethod" value="registerModule" />
diff --git a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/oidfed/TrustChainTestUtil.java b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/oidfed/TrustChainTestUtil.java
index 0f4e74b..14cbafc 100644
--- a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/oidfed/TrustChainTestUtil.java
+++ b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/oidfed/TrustChainTestUtil.java
@@ -25,6 +25,7 @@ import org.testng.Assert;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver;
 import com.fasterxml.jackson.databind.module.SimpleModule;
 import com.nimbusds.jose.JOSEException;
 import com.nimbusds.jose.JOSEObjectType;
@@ -40,11 +41,13 @@ import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;
 import com.nimbusds.jwt.JWTClaimsSet;
 import com.nimbusds.jwt.SignedJWT;
 
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityConfiguration;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.SubordinateStatement;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl.EntityConfigurationImpl;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl.SubordinateStatementImpl;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.jackson.InstantDeserializer;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.jackson.JWKSetDeserializer;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.impl.MetadataImpl;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.policy.FederationMetadataPolicyDeserializer;
 import net.shibboleth.oidc.metadata.policy.MetadataPolicy;
 
@@ -101,9 +104,9 @@ public class TrustChainTestUtil {
     public static EntityStatement<?> entityStatement(final SignedJWT jwt) {
         try {
             if (jwt.getJWTClaimsSet().getSubject().equals(jwt.getJWTClaimsSet().getIssuer())) {
-                return EntityConfiguration.parse(jwt, payloadObjectMapper());
+                return EntityConfigurationImpl.parse(jwt, payloadObjectMapper());
             }
-            return SubordinateStatement.parse(jwt, payloadObjectMapper());
+            return SubordinateStatementImpl.parse(jwt, payloadObjectMapper());
         } catch (JsonProcessingException | ParseException e) {
             Assert.fail("Could not construct entity configuration", e);
         }
@@ -116,6 +119,9 @@ public class TrustChainTestUtil {
         jacksonModule.addDeserializer(MetadataPolicy.class, new FederationMetadataPolicyDeserializer("scope"));
         jacksonModule.addDeserializer(JWKSet.class, new JWKSetDeserializer());
         jacksonModule.addDeserializer(Instant.class, new InstantDeserializer());
+        final SimpleAbstractTypeResolver jacksonResolver = new SimpleAbstractTypeResolver();
+        jacksonResolver.addMapping(Metadata.class, MetadataImpl.class);
+        jacksonModule.setAbstractTypes(jacksonResolver);
         final ObjectMapper objectMapper = new ObjectMapper();
         objectMapper.registerModule(jacksonModule);
         return objectMapper;
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 e2d1245..fae03f6 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
@@ -46,8 +46,9 @@ import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
 import net.minidev.json.JSONObject;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.TrustChainTestUtil;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityConfiguration;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityConfigurationPayload;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.trustmark.DefaultTrustMarkFetchingStrategy;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl.EntityConfigurationImpl;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.EntityConfigurationPayload;
 import net.shibboleth.shared.collection.CollectionSupport;
 
 /**
@@ -111,7 +112,7 @@ public class EntityConfigurationFlowTest extends AbstractFederationFlowTest {
     protected void assertEntityStatement(final Response response) throws ParseException {
         final EntityConfiguration entityStatement;
         try {
-            entityStatement = EntityConfiguration.parse(
+            entityStatement = EntityConfigurationImpl.parse(
                     SignedJWT.parse(response.toHTTPResponse().getContent()), payloadObjectMapper);
         } catch (JsonProcessingException | java.text.ParseException e) {
             Assert.fail();

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


More information about the commits mailing list