[java-idp-plugin-oidc-op-oidfed] 02/03: Add configurable cache container lifetime strategy for cases where response cannot be fetched
Codeberg
noreply at shibboleth.net
Thu Jan 22 11:41:11 UTC 2026
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch dev/CACHE-REFACTOR
in repository java-idp-plugin-oidc-op-oidfed.
View the commit online:
https://codeberg.org/Shibboleth/java-idp-plugin-oidc-op-oidfed/commit/4b6448eaf44fd2da87834db5e70164dbf7034f75
commit 4b6448eaf44fd2da87834db5e70164dbf7034f75
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Wed Jan 21 11:45:16 2026 +0200
Add configurable cache container lifetime strategy for cases where response cannot be fetched
- Covers for instance network issues
- Wired configuration properties for each metadata cache, all default to PT0S (no caching)
- idp.oidfed.cache.entityConfiguration.exceptionContainerLifetime
- idp.oidfed.cache.subordinateStatement.exceptionContainerLifetime
- idp.oidfed.cache.resolveEntity.exceptionContainerLifetime
- idp.oidfed.cache.trustMarkStatus.exceptionContainerLifetime
- idp.oidfed.cache.trustMark.exceptionContainerLifetime
---
...FederationEndpointResponseFetchingStrategy.java | 53 +++++++++++++++++++---
...DefaultEntityConfigurationFetchingStrategy.java | 13 ++++--
...ultResolveEntityTrustChainFetchingStrategy.java | 12 ++++-
...efaultSubordinateStatementFetchingStrategy.java | 13 ++++--
.../DefaultTrustMarkFetchingStrategy.java | 14 ++++--
.../DefaultTrustMarkStatusFetchingStrategy.java | 14 ++++--
.../META-INF/net.shibboleth.idp/postconfig.xml | 35 ++++++++++++++
.../flow/oidfed/AbstractFederationFlowTest.java | 2 +-
.../EntityConfigurationMetadataCacheTest.java | 21 +++++++++
.../SubordinateStatementMetadataCacheTest.java | 35 +++++++++++++-
10 files changed, 189 insertions(+), 23 deletions(-)
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/AbstractFederationEndpointResponseFetchingStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/AbstractFederationEndpointResponseFetchingStrategy.java
index 5eb34eb..7897a17 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/AbstractFederationEndpointResponseFetchingStrategy.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/AbstractFederationEndpointResponseFetchingStrategy.java
@@ -72,6 +72,9 @@ public abstract class
/** Strategy to fetch lifetime for container with invalid contents. */
@NonnullAfterInit private Function<CriteriaSet, Duration> criteriaToInvalidContainerLifetimeStrategy;
+ /** Strategy to fetch lifetime for containers whose contents could not be fetched. */
+ @NonnullAfterInit private Function<CriteriaSet, Duration> criteriaToExceptionContainerLifetimeStrategy;
+
/**
* Set the {@link HttpClient} to use.
*
@@ -140,6 +143,19 @@ public abstract class
Constraint.isNotNull(strategy, "Criteria to invalid container lifetime strategy cannot be null");
}
+ /**
+ * Set the strategy to fetch lifetime for container whose contents could not be fetched.
+ *
+ * @param strategy lifetime strategy
+ */
+ public void setCriteriaToExceptionContainerLifetimeStrategy(
+ @Nonnull final Function<CriteriaSet, Duration> strategy) {
+ checkSetterPreconditions();
+
+ criteriaToExceptionContainerLifetimeStrategy =
+ Constraint.isNotNull(strategy, "Criteria to exception container lifetime strategy cannot be null");
+ }
+
/** {@inheritDoc} */
@Override
protected void doInitialize() throws ComponentInitializationException {
@@ -160,6 +176,10 @@ public abstract class
throw new ComponentInitializationException(
"Criteria to invalid container lifetime strategy cannot be null");
}
+ if (criteriaToExceptionContainerLifetimeStrategy == null) {
+ throw new ComponentInitializationException(
+ "Criteria to exception container lifetime strategy cannot be null");
+ }
}
/** {@inheritDoc} */
@@ -187,6 +207,12 @@ public abstract class
return null;
}
final Instant invalidExpiration = Instant.now().plus(invalidLifetime);
+ final Duration exceptionLifetime = criteriaToExceptionContainerLifetimeStrategy.apply(criteria);
+ if (exceptionLifetime == null) {
+ log.warn("Could not fetch expiration time for exception container");
+ return null;
+ }
+ final Instant exceptionExpiration = Instant.now().plus(exceptionLifetime);
final ClassicHttpRequest httpRequest = initializeHttpRequest(criteria, requestData);
if (httpRequest == null) {
log.debug("Could not initialize HTTP request for {}", requestData);
@@ -199,13 +225,14 @@ public abstract class
throw new URISyntaxException(httpRequest.getUri().toString(), "Could not parse scheme");
}
HttpClientSecuritySupport.checkTLSCredentialEvaluated(httpContext, scheme);
- assert validExpiration != null; assert invalidExpiration != null;
- return parseHttpResponse(criteria, requestData, response, validExpiration, invalidExpiration);
+ assert validExpiration != null; assert invalidExpiration != null; assert exceptionExpiration != null;
+ return parseHttpResponse(criteria, requestData, response, validExpiration, invalidExpiration,
+ exceptionExpiration);
} catch (final ProtocolException | URISyntaxException | IOException e) {
log.debug("Unable to fetch resolve entity response via request data: {}", requestData, e);
+ assert exceptionExpiration != null;
+ return handleException(criteria, requestData, e, exceptionExpiration);
}
-
- return null;
}
/**
@@ -241,12 +268,26 @@ public abstract class
* @param response the HTTP response obtained from {@link #httpClient}
* @param validExpiration expiration instant for containers with valid content
* @param invalidExpiration expiration instant for container with invalid content
+ * @param exceptionExpiration expiration instant for container whose contents could not be fetched
* @return the response message container
* @throws ProtocolException if HTTP protocol violation occurs
* @throws IOException if generic I/O exception occurs
*/
@Nullable protected abstract C parseHttpResponse(@Nonnull final CriteriaSet criteria,
@Nonnull final R requestData, @Nullable final ClassicHttpResponse response,
- @Nonnull final Instant validExpiration, @Nonnull final Instant invalidExpiration)
- throws ProtocolException, IOException;
+ @Nonnull final Instant validExpiration, @Nonnull final Instant invalidExpiration,
+ @Nonnull final Instant exceptionExpiration) throws ProtocolException, IOException;
+
+ /**
+ * Handles the exception catched while communicating with the remote API.
+ *
+ * @param criteria criteria set
+ * @param requestData the request data
+ * @param throwable exception catched while communicating with the remote API
+ * @param expiration exoiration instant for container whose contents could not be fetched
+ * @return the container to be stored in the metadata cache
+ */
+ @Nullable protected abstract C handleException(@Nonnull final CriteriaSet criteria,
+ @Nonnull final R requestData, @Nonnull final Throwable throwable, @Nonnull final Instant expiration);
+
}
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 9e7e7a6..f59a82a 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
@@ -96,8 +96,8 @@ public class DefaultEntityConfigurationFetchingStrategy
/** {@inheritDoc} */
@Nullable protected RemoteEntityConfigurationContainer parseHttpResponse(@Nonnull final CriteriaSet criteria,
@Nonnull final String entityId, @Nullable final ClassicHttpResponse response,
- @Nonnull final Instant validExpiration, @Nonnull final Instant invalidExpiration)
- throws ProtocolException, IOException {
+ @Nonnull final Instant validExpiration, @Nonnull final Instant invalidExpiration,
+ @Nonnull final Instant nullExpiration) throws ProtocolException, IOException {
if (response != null) {
if (!HTTP_RESPONSE_CONTENT_TYPE.equals(response.getEntity().getContentType())) {
log.warn("Unexpected content type: {}", response.getEntity().getContentType());
@@ -121,10 +121,17 @@ public class DefaultEntityConfigurationFetchingStrategy
} catch (java.text.ParseException e) {
log.warn("Could not parse JWT from the response", e);
}
+ return new RemoteEntityConfigurationContainer(entityId, null, validExpiration, invalidExpiration);
} else {
log.debug("Unable to fetch entity configuration for: {} (null response)", entityId);
+ return new RemoteEntityConfigurationContainer(entityId, null, validExpiration, nullExpiration);
}
+ }
- return new RemoteEntityConfigurationContainer(entityId, null, validExpiration, invalidExpiration);
+ /** {@inheritDoc} */
+ @Nullable protected RemoteEntityConfigurationContainer handleException(@Nonnull final CriteriaSet criteria,
+ @Nonnull final String entityId, @Nonnull final Throwable throwable, @Nonnull final Instant expiration) {
+ return new RemoteEntityConfigurationContainer(entityId, null, expiration, expiration);
}
+
}
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 158c824..284c4dd 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
@@ -100,7 +100,7 @@ public class DefaultResolveEntityTrustChainFetchingStrategy
@Nullable protected RemoteResolveEntityResponseContainer parseHttpResponse(@Nonnull final CriteriaSet criteria,
@Nonnull final RemoteResolveEntityCacheContainerIdentifier identifier,
@Nullable final ClassicHttpResponse response, @Nonnull final Instant validExpiration,
- @Nonnull final Instant invalidExpiration)
+ @Nonnull final Instant invalidExpiration, @Nonnull final Instant nullExpiration)
throws ProtocolException, IOException {
if (response != null) {
if (!HTTP_RESPONSE_CONTENT_TYPE.equals(response.getEntity().getContentType())) {
@@ -126,10 +126,18 @@ public class DefaultResolveEntityTrustChainFetchingStrategy
} catch (java.text.ParseException e) {
log.warn("Could not parse JWT from the response", e);
}
+ return new RemoteResolveEntityResponseContainer(identifier, null, validExpiration, invalidExpiration);
} else {
log.debug("Unable to fetch resolve entity response: {} (null response)", identifier.getEndpoint());
+ return new RemoteResolveEntityResponseContainer(identifier, null, validExpiration, nullExpiration);
}
+ }
- return new RemoteResolveEntityResponseContainer(identifier, null, validExpiration, invalidExpiration);
+ /** {@inheritDoc} */
+ @Nullable protected RemoteResolveEntityResponseContainer handleException(@Nonnull final CriteriaSet criteria,
+ @Nonnull final RemoteResolveEntityCacheContainerIdentifier identifier, @Nonnull final Throwable exception,
+ @Nonnull final Instant expiration) {
+ return new RemoteResolveEntityResponseContainer(identifier, null, expiration, expiration);
}
+
}
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 03b4125..d031e0b 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
@@ -163,8 +163,8 @@ public class DefaultSubordinateStatementFetchingStrategy
/** {@inheritDoc} */
@Nullable protected RemoteSubordinateStatementContainer parseHttpResponse(@Nonnull final CriteriaSet criteria,
@Nonnull final SubordinateStatementCacheIdentifier id, @Nullable final ClassicHttpResponse response,
- @Nonnull final Instant validExpiration, @Nonnull final Instant invalidExpiration)
- throws ProtocolException, IOException {
+ @Nonnull final Instant validExpiration, @Nonnull final Instant invalidExpiration,
+ @Nonnull final Instant nullExpiration) throws ProtocolException, IOException {
if (response != null) {
if (!HTTP_RESPONSE_CONTENT_TYPE.equals(response.getEntity().getContentType())) {
log.warn("Unexpected content type: {}", response.getEntity().getContentType());
@@ -188,10 +188,17 @@ public class DefaultSubordinateStatementFetchingStrategy
} catch (java.text.ParseException e) {
log.warn("Could not parse JWT from the response", e);
}
+ return new RemoteSubordinateStatementContainer(id, null, validExpiration, invalidExpiration);
} else {
log.debug("Unable to fetch entity configuration for: {} (null response)", id);
+ return new RemoteSubordinateStatementContainer(id, null, validExpiration, nullExpiration);
}
+ }
- return new RemoteSubordinateStatementContainer(id, null, validExpiration, invalidExpiration);
+ /** {@inheritDoc} */
+ @Nullable protected RemoteSubordinateStatementContainer handleException(@Nonnull final CriteriaSet criteria,
+ @Nonnull final SubordinateStatementCacheIdentifier id, @Nonnull final Throwable exception,
+ @Nonnull final Instant expiration) {
+ return new RemoteSubordinateStatementContainer(id, null, expiration, expiration);
}
}
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 71d1c84..8ac59e1 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
@@ -97,8 +97,8 @@ public class DefaultTrustMarkFetchingStrategy
/** {@inheritDoc} */
@Nullable protected RemoteTrustMarkContainer parseHttpResponse(@Nonnull final CriteriaSet criteria,
@Nonnull final TrustMarkCacheIdentifier request, @Nullable final ClassicHttpResponse response,
- @Nonnull final Instant validExpiration, @Nonnull final Instant invalidExpiration)
- throws ProtocolException, IOException {
+ @Nonnull final Instant validExpiration, @Nonnull final Instant invalidExpiration,
+ @Nonnull final Instant nullExpiration) throws ProtocolException, IOException {
if (response != null) {
if (!HTTP_RESPONSE_CONTENT_TYPE.equals(response.getEntity().getContentType())) {
log.warn("Unexpected content type: {}", response.getEntity().getContentType());
@@ -122,10 +122,18 @@ public class DefaultTrustMarkFetchingStrategy
} catch (java.text.ParseException e) {
log.warn("Could not parse JWT from the response", e);
}
+ return new RemoteTrustMarkContainer(request, null, validExpiration, invalidExpiration);
} else {
log.debug("Unable to fetch trust mark: {} (null response)", request.getTrustMarkType());
+ return new RemoteTrustMarkContainer(request, null, validExpiration, nullExpiration);
}
+ }
- return new RemoteTrustMarkContainer(request, null, validExpiration, invalidExpiration);
+ /** {@inheritDoc} */
+ @Nullable protected RemoteTrustMarkContainer handleException(@Nonnull final CriteriaSet criteria,
+ @Nonnull final TrustMarkCacheIdentifier request, @Nonnull final Throwable exception,
+ @Nonnull final Instant expiration) {
+ return new RemoteTrustMarkContainer(request, null, expiration, expiration);
}
+
}
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 c6b472c..e6f87c4 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
@@ -96,8 +96,8 @@ public class DefaultTrustMarkStatusFetchingStrategy
/** {@inheritDoc} */
@Nullable protected RemoteTrustMarkStatusContainer parseHttpResponse(@Nonnull final CriteriaSet criteria,
@Nonnull final TrustMarkStatusCacheIdentifier identifier, @Nullable final ClassicHttpResponse response,
- @Nonnull final Instant validExpiration, @Nonnull final Instant invalidExpiration)
- throws ProtocolException, IOException {
+ @Nonnull final Instant validExpiration, @Nonnull final Instant invalidExpiration,
+ @Nonnull final Instant nullExpiration) throws ProtocolException, IOException {
if (response != null) {
if (!HTTP_RESPONSE_CONTENT_TYPE.equals(response.getEntity().getContentType())) {
log.warn("Unexpected content type: {}", response.getEntity().getContentType());
@@ -121,10 +121,18 @@ public class DefaultTrustMarkStatusFetchingStrategy
} catch (java.text.ParseException e) {
log.warn("Could not parse JWT from the response", e);
}
+ return new RemoteTrustMarkStatusContainer(identifier, null, validExpiration, invalidExpiration);
} else {
log.debug("Unable to fetch trust mark status: {} (null response)", identifier.getEndpoint());
+ return new RemoteTrustMarkStatusContainer(identifier, null, validExpiration, nullExpiration);
}
+ }
- return new RemoteTrustMarkStatusContainer(identifier, null, validExpiration, invalidExpiration);
+ /** {@inheritDoc} */
+ @Nullable protected RemoteTrustMarkStatusContainer handleException(@Nonnull final CriteriaSet criteria,
+ @Nonnull final TrustMarkStatusCacheIdentifier identifier, @Nonnull final Throwable exception,
+ @Nonnull final Instant expiration) {
+ return new RemoteTrustMarkStatusContainer(identifier, null, expiration, expiration);
}
+
}
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 95b4a1e..46b305c 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
@@ -114,6 +114,13 @@
</constructor-arg>
</bean>
</property>
+ <property name="criteriaToExceptionContainerLifetimeStrategy">
+ <bean parent="shibboleth.Functions.Constant">
+ <constructor-arg>
+ <bean class="java.time.Duration" factory-method="parse" c:_0="%{idp.oidfed.cache.entityConfiguration.exceptionContainerLifetime:PT0S}" />
+ </constructor-arg>
+ </bean>
+ </property>
</bean>
</property>
<property name="metadataFilterStrategy">
@@ -240,6 +247,13 @@
</constructor-arg>
</bean>
</property>
+ <property name="criteriaToExceptionContainerLifetimeStrategy">
+ <bean parent="shibboleth.Functions.Constant">
+ <constructor-arg>
+ <bean class="java.time.Duration" factory-method="parse" c:_0="%{idp.oidfed.cache.subordinateStatement.exceptionContainerLifetime:PT0S}" />
+ </constructor-arg>
+ </bean>
+ </property>
</bean>
</property>
</bean>
@@ -386,6 +400,13 @@
</constructor-arg>
</bean>
</property>
+ <property name="criteriaToExceptionContainerLifetimeStrategy">
+ <bean parent="shibboleth.Functions.Constant">
+ <constructor-arg>
+ <bean class="java.time.Duration" factory-method="parse" c:_0="%{idp.oidfed.cache.resolveEntity.exceptionContainerLifetime:PT0S}" />
+ </constructor-arg>
+ </bean>
+ </property>
</bean>
</property>
</bean>
@@ -505,6 +526,13 @@
</constructor-arg>
</bean>
</property>
+ <property name="criteriaToExceptionContainerLifetimeStrategy">
+ <bean parent="shibboleth.Functions.Constant">
+ <constructor-arg>
+ <bean class="java.time.Duration" factory-method="parse" c:_0="%{idp.oidfed.cache.trustMarkStatus.exceptionContainerLifetime:PT0S}" />
+ </constructor-arg>
+ </bean>
+ </property>
</bean>
</property>
</bean>
@@ -583,6 +611,13 @@
</constructor-arg>
</bean>
</property>
+ <property name="criteriaToExceptionContainerLifetimeStrategy">
+ <bean parent="shibboleth.Functions.Constant">
+ <constructor-arg>
+ <bean class="java.time.Duration" factory-method="parse" c:_0="%{idp.oidfed.cache.trustMark.exceptionContainerLifetime:PT0S}" />
+ </constructor-arg>
+ </bean>
+ </property>
</bean>
</property>
</bean>
diff --git a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AbstractFederationFlowTest.java b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AbstractFederationFlowTest.java
index 17d76b2..5cb4e4f 100644
--- a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AbstractFederationFlowTest.java
+++ b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AbstractFederationFlowTest.java
@@ -113,7 +113,7 @@ public class AbstractFederationFlowTest extends AbstractOidcFlowTest {
@Autowired
@Qualifier("shibboleth.oidfed.HttpClient")
- HttpClient federationHttpClient;
+ protected HttpClient federationHttpClient;
protected AbstractFederationFlowTest(final String flowId) {
super(flowId);
diff --git a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/cache/EntityConfigurationMetadataCacheTest.java b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/cache/EntityConfigurationMetadataCacheTest.java
index ba9227e..5eee569 100644
--- a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/cache/EntityConfigurationMetadataCacheTest.java
+++ b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/cache/EntityConfigurationMetadataCacheTest.java
@@ -14,6 +14,10 @@
package net.shibboleth.idp.plugin.oidc.op.profile.flow.oidfed.cache;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.Mockito.when;
+
import java.io.IOException;
import java.net.URISyntaxException;
import java.time.Instant;
@@ -224,6 +228,23 @@ public class EntityConfigurationMetadataCacheTest extends AbstractFederationFlow
assertNoEntityConfiguration(entityId);
}
+ @Test
+ public void testNullResponse()
+ throws MetadataCacheException, UnsupportedOperationException, IOException, URISyntaxException {
+ final String entityId = uniqueClientId();
+ mapResponse(entityConfigurationUrl(entityId), null);
+ assertNoEntityConfiguration(entityId);
+ }
+
+ @Test
+ public void testExceptionResponse()
+ throws MetadataCacheException, UnsupportedOperationException, IOException, URISyntaxException {
+ final String entityId = uniqueClientId();
+ when(federationHttpClient.executeOpen(any(), argThat(new RequestUriMatcher(entityConfigurationUrl(entityId))),
+ any())).thenThrow(IOException.class);
+ assertNoEntityConfiguration(entityId);
+ }
+
protected void assertNoEntityConfiguration(final String entityId) {
try {
final List<RemoteEntityConfigurationContainer> result =
diff --git a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/cache/SubordinateStatementMetadataCacheTest.java b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/cache/SubordinateStatementMetadataCacheTest.java
index 19b8970..2afb1d9 100644
--- a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/cache/SubordinateStatementMetadataCacheTest.java
+++ b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/cache/SubordinateStatementMetadataCacheTest.java
@@ -14,6 +14,10 @@
package net.shibboleth.idp.plugin.oidc.op.profile.flow.oidfed.cache;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.Mockito.when;
+
import java.io.IOException;
import java.net.URISyntaxException;
import java.time.Instant;
@@ -229,15 +233,42 @@ public class SubordinateStatementMetadataCacheTest extends AbstractFederationFlo
assertNoSubordinateStatement(entityId);
}
+ @Test
+ public void testNullResponse()
+ throws MetadataCacheException, UnsupportedOperationException, IOException, URISyntaxException {
+ final String entityId = uniqueClientId();
+ mapResponse(entityConfigurationUrl(anchorId), mockResponse(trustedAnchorConfiguration()));
+ assertNoSubordinateStatement(entityId, false);
+ }
+
+ @Test
+ public void testExceptionResponse()
+ throws MetadataCacheException, UnsupportedOperationException, IOException, URISyntaxException {
+ final String entityId = uniqueClientId();
+ mapResponse(entityConfigurationUrl(anchorId), mockResponse(trustedAnchorConfiguration()));
+ when(federationHttpClient.executeOpen(any(),
+ argThat(new RequestUriMatcher(subordinateStatementUrl(anchorFetchEndpoint, entityId))),
+ any())).thenThrow(IOException.class);
+ assertNoSubordinateStatement(entityId, false);
+ }
+
protected void assertNoSubordinateStatement(final String entityId) {
+ assertNoSubordinateStatement(entityId, true);
+ }
+
+ protected void assertNoSubordinateStatement(final String entityId, final boolean containerExists) {
try {
final List<RemoteSubordinateStatementContainer> result =
subordinateStatementCache.get(new CriteriaSet(new SubjectEntityIDCriterion(entityId),
new ResponseContainerExpirationCriterion(Instant.now().plusSeconds(300)),
new IssuerEntityIDCriterion(anchorId)));
Assert.assertNotNull(result);
- Assert.assertEquals(result.size(), 1);
- Assert.assertNull(result.get(0).getStatement());
+ if (containerExists) {
+ Assert.assertEquals(result.size(), 1);
+ Assert.assertNull(result.get(0).getStatement());
+ } else {
+ Assert.assertEquals(result.size(), 0);
+ }
} catch (MetadataCacheException e) {
Assert.fail("Could not resolve entity configuration", e);
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list