[java-oidc-common] 02/02: Stub out generic metadata filtering and validation
Phil Smart
philip.smart at jisc.ac.uk
Thu Sep 2 15:40:53 UTC 2021
This is an automated email from the git hooks/post-receive script.
philsmart pushed a commit to branch dev/JCOMOIDC-23
in repository java-oidc-common.
View the commit online:
http://git.shibboleth.net/view/?p=java-oidc-common.git;a=commit;h=01c314657f6fa429151770568a374791e24fea20
commit 01c314657f6fa429151770568a374791e24fea20
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Thu Sep 2 16:40:42 2021 +0100
Stub out generic metadata filtering and validation
Needs thinking about.
---
.../oidc/metadata/filter/MetadataSource.java | 56 +++++++++++
...bstractDynamicOIDCProviderMetadataResolver.java | 103 ++++++++++++++++++++-
.../impl/AbstractOIDCMetadataResolver.java | 9 ++
.../HTTPProviderConfigurationMetadataResolver.java | 35 +++++++
4 files changed, 201 insertions(+), 2 deletions(-)
diff --git a/oidc-common-metadata-api/src/main/java/net/shibboleth/oidc/metadata/filter/MetadataSource.java b/oidc-common-metadata-api/src/main/java/net/shibboleth/oidc/metadata/filter/MetadataSource.java
new file mode 100644
index 0000000..7a6f03d
--- /dev/null
+++ b/oidc-common-metadata-api/src/main/java/net/shibboleth/oidc/metadata/filter/MetadataSource.java
@@ -0,0 +1,56 @@
+package net.shibboleth.oidc.metadata.filter;
+
+import javax.annotation.Nullable;
+
+import net.shibboleth.oidc.metadata.filter.MetadataFilterContext.Data;
+
+/**
+ * Data object for {@link MetadataFilterContext} intended to hold information about the source of the
+ * metadata currently being processed.
+
+ */
+public class MetadataSource implements Data {
+
+ /** An identifier for the source of the metadata, typically the resolver ID. */
+ @Nullable private String sourceId;
+
+ /** Flag indicating whether the metadata source is trusted. */
+ private boolean trusted;
+
+ /**
+ * Get identifier of the metadata source.
+ *
+ * @return source identifier
+ */
+ @Nullable public String getSourceId() {
+ return sourceId;
+ }
+
+ /**
+ * Set identifier of the metadata source.
+ *
+ * @param id source identifier
+ */
+ public void setSourceId(@Nullable final String id) {
+ sourceId = id;
+ }
+
+ /**
+ * Get whether the metadata source is trusted.
+ *
+ * @return true if trusted, false if not
+ */
+ public boolean isTrusted() {
+ return trusted;
+ }
+
+ /**
+ * Set whether the metadata source is trusted.
+ *
+ * @param flag true if trusted, false if not
+ */
+ public void setTrusted(final boolean flag) {
+ this.trusted = flag;
+ }
+
+}
diff --git a/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/impl/AbstractDynamicOIDCProviderMetadataResolver.java b/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/impl/AbstractDynamicOIDCProviderMetadataResolver.java
index 9e39084..4a7709c 100644
--- a/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/impl/AbstractDynamicOIDCProviderMetadataResolver.java
+++ b/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/impl/AbstractDynamicOIDCProviderMetadataResolver.java
@@ -11,6 +11,7 @@ import java.util.concurrent.locks.Lock;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import org.opensaml.core.xml.XMLObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -20,7 +21,8 @@ import net.shibboleth.oidc.metadata.DynamicBackingStore;
import net.shibboleth.oidc.metadata.DynamicOIDCProviderMetadataResolver;
import net.shibboleth.oidc.metadata.MetadataManagementData;
import net.shibboleth.oidc.metadata.filter.FilterException;
-import net.shibboleth.oidc.metadata.filter.MetadataFilter;
+import net.shibboleth.oidc.metadata.filter.MetadataFilterContext;
+import net.shibboleth.oidc.metadata.filter.MetadataSource;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
import net.shibboleth.utilities.java.support.annotation.constraint.Positive;
@@ -234,6 +236,15 @@ public abstract class AbstractDynamicOIDCProviderMetadataResolver<MetadataIdenti
ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+ // Find identifier from criteria (impl specific)
+
+ // Lock and check cache for metadata relating to entity
+ // // If exists check it should not be refershed.
+
+ // if not in cache or requires refresh lookup from source.
+
+ // Filter candidates
+
//final Context contextResolve = MetricsSupport.startTimer(timerResolve);
try {
Iterable<MetadataType> candidates = null;
@@ -374,7 +385,18 @@ public abstract class AbstractDynamicOIDCProviderMetadataResolver<MetadataIdenti
throws FilterException, ResolverException {
- // TODO filter metadata if required and configured.
+ // Filter metadata if required and configured.
+ final MetadataType filteredMetadata = filterMetadata(prepareForFiltering(metadata));
+ if (filteredMetadata == null) {
+ log.info("{} Metadata filtering process produced a null document, resulting in an empty data set",
+ getLogPrefix());
+ finalizeMetadataProcessing(metadata);
+ return;
+ }
+
+ if (!isNewMetadataValid(filteredMetadata, expectedIdentifier)) {
+ return;
+ }
// determine identifier
final MetadataIdentifier identifier = extractIdentifier(metadata);
@@ -412,12 +434,89 @@ public abstract class AbstractDynamicOIDCProviderMetadataResolver<MetadataIdenti
mgmtData.setRefreshTriggerTime(computeRefreshTriggerTime(mgmtData.getExpirationTime(), now));
log.debug("{} Computed refresh trigger time: {}", getLogPrefix(), mgmtData.getRefreshTriggerTime());
+ log.info("{} Successfully loaded new EntityDescriptor with entityID '{}' from {}",
+ getLogPrefix(), identifier,
+ fromPersistentCache ? "persistent cache" : "origin source");
+
+ //finalize processing of both the filtered and original metadata.
+ finalizeMetadataProcessing(filteredMetadata);
+ finalizeMetadataProcessing(metadata);
+
//TODO log the new metadata expiration
//TODO save metadata to persistent cache if enabled.
}
+ /**
+ * Check the metadata is valid e.g. is the correct type. Is implementation specific.
+ *
+ * @param metadata the metadata to check.
+ * @param expectedIdentifier the expected identifier of the metadata.
+ *
+ * @return true iff the metadata is valid, false otherwise.
+ *
+ * @throws FilterException if there is a fatal error validating the metadata.
+ */
+ @Nonnull protected abstract boolean isNewMetadataValid(@Nonnull final MetadataType metadata,
+ @Nonnull final MetadataIdentifier expectedIdentifier) throws ResolverException;
+
+ /**
+ * Prepare the object for filtering. This is implementation specific.
+ *
+ * @param input the metadata on which to operate
+ *
+ * @return the metadata instance to be filtered
+ */
+ @Nonnull protected abstract MetadataType prepareForFiltering(@Nonnull final MetadataType input);
+
+ /**
+ * Finalize the metadata object after processing. This is implementation specific.
+ *
+ * @param input the metadata on which to operate
+ *
+ * @return the metadata instance to be filtered
+ */
+ @Nonnull protected abstract void finalizeMetadataProcessing(@Nonnull final MetadataType input);
+
+ /**
+ * Filters the given metadata.
+ *
+ * @param metadata the metadata to be filtered
+ *
+ * @return the filtered metadata
+ *
+ * @throws FilterException thrown if there is an error filtering the metadata
+ */
+ @Nullable protected MetadataType filterMetadata(@Nullable final MetadataType metadata) throws FilterException {
+ if (getMetadataFilter() != null) {
+ log.debug("{} Applying metadata filter", getLogPrefix());
+ return getMetadataFilter().filter(metadata, newFilterContext());
+ }
+ return metadata;
+ }
+
+ /**
+ * Get a new instance of {@link MetadataFilterContext} to be used when filtering metadata.
+ *
+ * <p>
+ * This default implementation will just return an empty context. Subclasses would override
+ * to add contextual info specific to the implementation.
+ * </p>
+ *
+ * @return the new filter context instance
+ */
+ @Nonnull protected MetadataFilterContext newFilterContext() {
+
+ final MetadataSource source = new MetadataSource();
+ source.setSourceId(getId());
+
+ final MetadataFilterContext context = new MetadataFilterContext();
+ context.add(source);
+
+ return context;
+ }
+
/**
* Compute the effective expiration time for the specified metadata.
*
diff --git a/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/impl/AbstractOIDCMetadataResolver.java b/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/impl/AbstractOIDCMetadataResolver.java
index 8d95ef0..6a266c7 100644
--- a/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/impl/AbstractOIDCMetadataResolver.java
+++ b/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/impl/AbstractOIDCMetadataResolver.java
@@ -68,6 +68,15 @@ public abstract class AbstractOIDCMetadataResolver<MetadataIdentifier, MetadataT
return logPrefix;
}
+ /**
+ * Gets the metadata filter applied to the metadata.
+ *
+ * @return the metadata filter applied to the metadata
+ */
+ @Nullable public MetadataFilter<MetadataType> getMetadataFilter() {
+ return mdFilter;
+ }
+
/**
* Set the entity backing store currently in use by the metadata resolver.
diff --git a/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/impl/HTTPProviderConfigurationMetadataResolver.java b/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/impl/HTTPProviderConfigurationMetadataResolver.java
index 4c6eff5..4345015 100644
--- a/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/impl/HTTPProviderConfigurationMetadataResolver.java
+++ b/oidc-common-metadata-impl/src/main/java/net/shibboleth/oidc/metadata/impl/HTTPProviderConfigurationMetadataResolver.java
@@ -4,6 +4,7 @@ import java.io.IOException;
import java.time.Instant;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.function.BiFunction;
@@ -234,6 +235,40 @@ public class HTTPProviderConfigurationMetadataResolver
}
+ @Override
+ @Nonnull protected boolean isNewMetadataValid(@Nonnull final OIDCProviderMetadata metadata,
+ @Nonnull final Issuer expectedIdentifier) throws ResolverException {
+
+ if (!Objects.equals(metadata.getIssuer(), expectedIdentifier)) {
+ log.warn("{} New metadata's issuer '{}' does not match expected issuer '{}', will not process",
+ getLogPrefix(), metadata.getIssuer(), expectedIdentifier);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * No-op method for this resolver.
+ */
+ @Override
+ @Nonnull protected OIDCProviderMetadata prepareForFiltering(@Nonnull final OIDCProviderMetadata input) {
+ //do nothing, just return
+ return input;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * No-op method for this resolver.
+ */
+ @Override
+ @Nonnull protected void finalizeMetadataProcessing(@Nonnull final OIDCProviderMetadata input) {
+ //do nothing, just return
+ return;
+ }
+
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list