[java-idp-oidc] branch dev/JOIDC-222 updated: JOIDC-222 - Support for OpenID Federation
Henri Mikkonen
henri.mikkonen at iki.fi
Tue Aug 12 12:06:43 UTC 2025
This is an automated email from the git hooks/post-receive script.
hjmikkon pushed a commit to branch dev/JOIDC-222
in repository java-idp-oidc.
View the commit online:
http://git.shibboleth.net/view/?p=java-idp-oidc.git;a=commit;h=369af52d51988b1b9ab9a4afeb7e1a46380b61cc
The following commit(s) were added to refs/heads/dev/JOIDC-222 by this push:
new 369af52d JOIDC-222 - Support for OpenID Federation
369af52d is described below
commit 369af52d51988b1b9ab9a4afeb7e1a46380b61cc
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Tue Aug 12 15:06:27 2025 +0300
JOIDC-222 - Support for OpenID Federation
https://shibboleth.atlassian.net/browse/JOIDC-222
Harmonised entity configuration and resolve entity API for caching the response caching
- Caching time for success responses set in the same way via OIDFederationResponseCachingProfileConfiguration
- Similarly to resolve entity API, also entity configuration caching now exploits metadata cache instead of (in-memory) storage service
- Success responses are stored in the cache
---
...FederationRegistrationProfileConfiguration.java | 13 ++
...erationResponseCachingProfileConfiguration.java | 89 +++++++++++++
...CachedErrorResponseLifetimeLookupFunction.java} | 2 +-
...chedSuccessResponseLifetimeLookupFunction.java} | 8 +-
...ionEntityConfigurationProfileConfiguration.java | 46 +------
...ederationResolveEntityProfileConfiguration.java | 47 +------
...ionEntityConfigurationProfileConfiguration.java | 16 +--
...ederationResolveEntityProfileConfiguration.java | 16 +--
...rationResponseCachingProfileConfiguration.java} | 23 +---
...ionResponseContainerExpirationTimeStrategy.java | 59 ++++++++
...tityConfigurationResponseFetchingStrategy.java} | 24 ++--
...faultResolveEntityResponseFetchingStrategy.java | 6 +-
...Container.java => NimbusResponseContainer.java} | 25 +---
...Criterion.java => NimbusResponseCriterion.java} | 10 +-
.../metadata/ResolveEntityResponseContainer.java | 29 +---
...a => ResponseContainerExpirationCriterion.java} | 8 +-
.../BuildResolveEntityErrorResponseFromEvent.java | 36 ++---
...ormOutboundFederationConfigurationResponse.java | 148 ++++++++++++++++-----
.../impl/FormOutboundResolveEntityResponse.java | 71 +++++-----
...> LookupCachedEntityConfigurationResponse.java} | 71 +++++-----
...java => LookupCachedResolveEntityResponse.java} | 45 ++++---
.../oidfed/profile/impl/OidFederationEventIds.java | 6 +
....java => RelyingPartyCachedMessageContext.java} | 18 ++-
.../profile/impl/ValidateResolveEntityRequest.java | 28 ++--
.../profile/impl/ValidateSelectedTrustChain.java | 23 ++--
...achedEntityStatementLifetimeLookupFunction.java | 52 --------
.../entity-configuration-beans.xml | 38 ++++--
.../entity-configuration-flow.xml | 27 +---
.../oidfed/resolve-entity/resolve-entity-beans.xml | 4 +-
.../oidfed/resolve-entity/resolve-entity-flow.xml | 2 +-
.../shibboleth/idp/module/conf/relying-party.xml | 2 +-
31 files changed, 517 insertions(+), 475 deletions(-)
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/AbstractOIDFederationRegistrationProfileConfiguration.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/AbstractOIDFederationRegistrationProfileConfiguration.java
index 219e6d61..fb3931e5 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/AbstractOIDFederationRegistrationProfileConfiguration.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/AbstractOIDFederationRegistrationProfileConfiguration.java
@@ -1,3 +1,16 @@
+/*
+ * 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.config;
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/AbstractOIDFederationResponseCachingProfileConfiguration.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/AbstractOIDFederationResponseCachingProfileConfiguration.java
new file mode 100644
index 00000000..654f958a
--- /dev/null
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/AbstractOIDFederationResponseCachingProfileConfiguration.java
@@ -0,0 +1,89 @@
+/*
+ * 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.config;
+
+import java.time.Duration;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.shibboleth.profile.config.AbstractConditionalProfileConfiguration;
+import net.shibboleth.shared.annotation.ParameterName;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.annotation.constraint.Positive;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.logic.FunctionSupport;
+
+/**
+ * Abstract implementation class for profile configurations related OpenID Federation response caching configuration.
+ */
+public abstract class AbstractOIDFederationResponseCachingProfileConfiguration
+ extends AbstractConditionalProfileConfiguration
+ implements OIDFederationResponseCachingProfileConfiguration {
+
+ /** Lookup function to supply cached success response lifetime. */
+ @Nonnull private Function<ProfileRequestContext,Duration> cachedSuccessResponseLifetimeLookupStrategy;
+
+ /**
+ * Constructor.
+ *
+ * @param id ID of the communication profile, never null or empty
+ */
+ public AbstractOIDFederationResponseCachingProfileConfiguration(
+ @Nonnull @NotEmpty @ParameterName(name="id") final String id) {
+ super(id);
+ cachedSuccessResponseLifetimeLookupStrategy = FunctionSupport.constant(Duration.ofMinutes(5));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Positive @Nonnull
+ public Duration getCachedSuccessResponseLifetime(@Nullable final ProfileRequestContext profileRequestContext) {
+ final Duration lifetime = cachedSuccessResponseLifetimeLookupStrategy.apply(profileRequestContext);
+
+ Constraint.isTrue(lifetime != null && !lifetime.isZero() && !lifetime.isNegative(),
+ "Success response lifetime must be greater than 0");
+ assert lifetime != null;
+ return lifetime;
+ }
+
+ /**
+ * Set the lifetime of a cached success response.
+ *
+ * @param lifetime lifetime of a cached success response
+ */
+ public void setCachedSuccessResponseLifetime(@Positive @Nonnull final Duration lifetime) {
+ final Duration successLifetime = Constraint.isNotNull(lifetime,
+ "Cached success response lifetime cannot be null");
+ Constraint.isTrue(!successLifetime.isZero() && !successLifetime.isNegative(),
+ "Cached success response lifetime must be greater than 0");
+
+ cachedSuccessResponseLifetimeLookupStrategy = FunctionSupport.constant(successLifetime);
+ }
+
+ /**
+ * Set a lookup strategy for the cached success response lifetime.
+ *
+ * @param strategy lookup strategy
+ */
+ public void setCachedSuccessResponseLifetimeLookupStrategy(
+ @Nullable final Function<ProfileRequestContext,Duration> strategy) {
+ cachedSuccessResponseLifetimeLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
+ }
+
+}
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/ResolveEntityCachedErrorResponseLifetimeLookupFunction.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/CachedErrorResponseLifetimeLookupFunction.java
similarity index 96%
rename from idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/ResolveEntityCachedErrorResponseLifetimeLookupFunction.java
rename to idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/CachedErrorResponseLifetimeLookupFunction.java
index d22579c7..01ded1d0 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/ResolveEntityCachedErrorResponseLifetimeLookupFunction.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/CachedErrorResponseLifetimeLookupFunction.java
@@ -29,7 +29,7 @@ import net.shibboleth.profile.context.navigate.AbstractRelyingPartyLookupFunctio
*
* <p>If a specific setting is unavailable, a null value is returned.</p>
*/
-public class ResolveEntityCachedErrorResponseLifetimeLookupFunction
+public class CachedErrorResponseLifetimeLookupFunction
extends AbstractRelyingPartyLookupFunction<Duration> {
/** {@inheritDoc} */
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/ResolveEntityCachedSuccessResponseLifetimeLookupFunction.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/CachedSuccessResponseLifetimeLookupFunction.java
similarity index 80%
rename from idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/ResolveEntityCachedSuccessResponseLifetimeLookupFunction.java
rename to idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/CachedSuccessResponseLifetimeLookupFunction.java
index 1ffecda0..b083076c 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/ResolveEntityCachedSuccessResponseLifetimeLookupFunction.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/CachedSuccessResponseLifetimeLookupFunction.java
@@ -25,11 +25,11 @@ import net.shibboleth.profile.context.navigate.AbstractRelyingPartyLookupFunctio
/**
* A function that returns
- * {@link OIDFederationResolveEntityProfileConfiguration#getCachedSuccessResponseLifetime(ProfileRequestContext)}.
+ * {@link OIDFederationResponseCachingProfileConfiguration#getCachedSuccessResponseLifetime(ProfileRequestContext)}.
*
* <p>If a specific setting is unavailable, a null value is returned.</p>
*/
-public class ResolveEntityCachedSuccessResponseLifetimeLookupFunction
+public class CachedSuccessResponseLifetimeLookupFunction
extends AbstractRelyingPartyLookupFunction<Duration> {
/** {@inheritDoc} */
@@ -37,8 +37,8 @@ public class ResolveEntityCachedSuccessResponseLifetimeLookupFunction
@Nullable public Duration apply(@Nullable final ProfileRequestContext input) {
return Optional.ofNullable(getRelyingPartyContextLookupStrategy().apply(input))
.map(relyingPartyContext -> relyingPartyContext.getProfileConfig())
- .filter(OIDFederationResolveEntityProfileConfiguration.class::isInstance)
- .map(OIDFederationResolveEntityProfileConfiguration.class::cast)
+ .filter(OIDFederationResponseCachingProfileConfiguration.class::isInstance)
+ .map(OIDFederationResponseCachingProfileConfiguration.class::cast)
.map(config -> config.getCachedSuccessResponseLifetime(input))
.orElse(null);
}
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/DefaultOIDFederationEntityConfigurationProfileConfiguration.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/DefaultOIDFederationEntityConfigurationProfileConfiguration.java
index bd020687..c885f7a6 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/DefaultOIDFederationEntityConfigurationProfileConfiguration.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/DefaultOIDFederationEntityConfigurationProfileConfiguration.java
@@ -25,7 +25,6 @@ import javax.annotation.Nullable;
import org.opensaml.profile.context.ProfileRequestContext;
-import net.shibboleth.profile.config.AbstractConditionalProfileConfiguration;
import net.shibboleth.shared.annotation.constraint.NonnullElements;
import net.shibboleth.shared.annotation.constraint.NotEmpty;
import net.shibboleth.shared.annotation.constraint.NotLive;
@@ -38,8 +37,9 @@ import net.shibboleth.shared.logic.FunctionSupport;
/**
* Implementation of a profile configuration for the OpenID Federation Entity Configuration.
*/
-public class DefaultOIDFederationEntityConfigurationProfileConfiguration extends AbstractConditionalProfileConfiguration
- implements OIDFederationEntityConfigurationProfileConfiguration {
+public class DefaultOIDFederationEntityConfigurationProfileConfiguration
+ extends AbstractOIDFederationResponseCachingProfileConfiguration
+ implements OIDFederationEntityConfigurationProfileConfiguration {
/** OIDC provider information profile counter name. */
@Nonnull @NotEmpty public static final String PROFILE_COUNTER = "net.shibboleth.idp.profiles.oidfed.configuration";
@@ -53,9 +53,6 @@ public class DefaultOIDFederationEntityConfigurationProfileConfiguration extends
/** Lookup function to supply entity statement lifetime. */
@Nonnull private Function<ProfileRequestContext,Duration> entityStatementLifetimeLookupStrategy;
- /** Lookup function to supply cached entity statement lifetime. */
- @Nonnull private Function<ProfileRequestContext,Duration> cachedEntityStatementLifetimeLookupStrategy;
-
/** Lookup function to supply strategy bi-function for manipulating entity statement claims set. */
@Nonnull
private Function<ProfileRequestContext,BiFunction<ProfileRequestContext,Map<String,Object>,Map<String,Object>>>
@@ -78,7 +75,6 @@ public class DefaultOIDFederationEntityConfigurationProfileConfiguration extends
issuerLookupStrategy = FunctionSupport.constant(null);
authorityHintsLookupStrategy = FunctionSupport.constant(CollectionSupport.emptyList());
entityStatementLifetimeLookupStrategy = FunctionSupport.constant(Duration.ofHours(24));
- cachedEntityStatementLifetimeLookupStrategy = FunctionSupport.constant(Duration.ofSeconds(10));
entityStatementClaimsSetManipulationStrategyLookupStrategy = FunctionSupport.constant(null);
}
@@ -169,42 +165,6 @@ public class DefaultOIDFederationEntityConfigurationProfileConfiguration extends
entityStatementLifetimeLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
}
- /** {@inheritDoc} */
- @Override
- @Positive @Nonnull
- public Duration getCachedEntityStatementLifetime(@Nullable final ProfileRequestContext profileRequestContext) {
- final Duration lifetime = cachedEntityStatementLifetimeLookupStrategy.apply(profileRequestContext);
-
- Constraint.isTrue(lifetime != null && !lifetime.isZero() && !lifetime.isNegative(),
- "Entity statement lifetime must be greater than 0");
- assert lifetime != null;
- return lifetime;
- }
-
- /**
- * Set the lifetime of a cached entity statement.
- *
- * @param lifetime lifetime of a cached entity statement
- */
- public void setCachedEntityStatementLifetime(@Positive @Nonnull final Duration lifetime) {
- final Duration statementLifetime = Constraint.isNotNull(lifetime,
- "Cached entity statement lifetime cannot be null");
- Constraint.isTrue(!statementLifetime.isZero() && !statementLifetime.isNegative(),
- "Cached entity statement lifetime must be greater than 0");
-
- cachedEntityStatementLifetimeLookupStrategy = FunctionSupport.constant(statementLifetime);
- }
-
- /**
- * Set a lookup strategy for the cached entity statement lifetime.
- *
- * @param strategy lookup strategy
- */
- public void setCachedEntityStatementLifetimeLookupStrategy(
- @Nullable final Function<ProfileRequestContext,Duration> strategy) {
- cachedEntityStatementLifetimeLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
- }
-
/** {@inheritDoc} */
@Override
@Nullable
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/DefaultOIDFederationResolveEntityProfileConfiguration.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/DefaultOIDFederationResolveEntityProfileConfiguration.java
index a0dfb3d3..ca140f84 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/DefaultOIDFederationResolveEntityProfileConfiguration.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/DefaultOIDFederationResolveEntityProfileConfiguration.java
@@ -22,7 +22,6 @@ import javax.annotation.Nullable;
import org.opensaml.profile.context.ProfileRequestContext;
-import net.shibboleth.profile.config.AbstractConditionalProfileConfiguration;
import net.shibboleth.shared.annotation.constraint.NotEmpty;
import net.shibboleth.shared.annotation.constraint.Positive;
import net.shibboleth.shared.logic.Constraint;
@@ -31,8 +30,9 @@ import net.shibboleth.shared.logic.FunctionSupport;
/**
* Implementation of a profile configuration for the OpenID Federation Resolve Entity.
*/
-public class DefaultOIDFederationResolveEntityProfileConfiguration extends AbstractConditionalProfileConfiguration
- implements OIDFederationResolveEntityProfileConfiguration {
+public class DefaultOIDFederationResolveEntityProfileConfiguration
+ extends AbstractOIDFederationResponseCachingProfileConfiguration
+ implements OIDFederationResolveEntityProfileConfiguration {
/** OIDC provider information profile counter name. */
@Nonnull @NotEmpty public static final String PROFILE_COUNTER = "net.shibboleth.idp.profiles.oidfed.resolve-entity";
@@ -40,9 +40,6 @@ public class DefaultOIDFederationResolveEntityProfileConfiguration extends Abstr
/** Lookup function to override issuer value. */
@Nonnull private Function<ProfileRequestContext,String> issuerLookupStrategy;
- /** Lookup function to supply cached success response lifetime. */
- @Nonnull private Function<ProfileRequestContext,Duration> cachedSuccessResponseLifetimeLookupStrategy;
-
/** Lookup function to supply cached error response lifetime. */
@Nonnull private Function<ProfileRequestContext,Duration> cachedErrorResponseLifetimeLookupStrategy;
@@ -61,7 +58,6 @@ public class DefaultOIDFederationResolveEntityProfileConfiguration extends Abstr
public DefaultOIDFederationResolveEntityProfileConfiguration(@Nonnull @NotEmpty final String profileId) {
super(profileId);
issuerLookupStrategy = FunctionSupport.constant(null);
- cachedSuccessResponseLifetimeLookupStrategy = FunctionSupport.constant(Duration.ofMinutes(5));
cachedErrorResponseLifetimeLookupStrategy = FunctionSupport.constant(Duration.ofMinutes(5));
}
@@ -89,42 +85,6 @@ public class DefaultOIDFederationResolveEntityProfileConfiguration extends Abstr
issuerLookupStrategy = Constraint.isNotNull(strategy, "Issuer lookup strategy cannot be null");
}
- /** {@inheritDoc} */
- @Override
- @Positive @Nonnull
- public Duration getCachedSuccessResponseLifetime(@Nullable final ProfileRequestContext profileRequestContext) {
- final Duration lifetime = cachedSuccessResponseLifetimeLookupStrategy.apply(profileRequestContext);
-
- Constraint.isTrue(lifetime != null && !lifetime.isZero() && !lifetime.isNegative(),
- "Success response lifetime must be greater than 0");
- assert lifetime != null;
- return lifetime;
- }
-
- /**
- * Set the lifetime of a cached success response.
- *
- * @param lifetime lifetime of a cached success response
- */
- public void setCachedSuccessResponseLifetime(@Positive @Nonnull final Duration lifetime) {
- final Duration successLifetime = Constraint.isNotNull(lifetime,
- "Cached success response lifetime cannot be null");
- Constraint.isTrue(!successLifetime.isZero() && !successLifetime.isNegative(),
- "Cached success response lifetime must be greater than 0");
-
- cachedSuccessResponseLifetimeLookupStrategy = FunctionSupport.constant(successLifetime);
- }
-
- /**
- * Set a lookup strategy for the cached success response lifetime.
- *
- * @param strategy lookup strategy
- */
- public void setCachedSuccessResponseLifetimeLookupStrategy(
- @Nullable final Function<ProfileRequestContext,Duration> strategy) {
- cachedSuccessResponseLifetimeLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
- }
-
/** {@inheritDoc} */
@Override
@Positive @Nonnull
@@ -160,5 +120,4 @@ public class DefaultOIDFederationResolveEntityProfileConfiguration extends Abstr
@Nullable final Function<ProfileRequestContext,Duration> strategy) {
cachedErrorResponseLifetimeLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
}
-
}
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/OIDFederationEntityConfigurationProfileConfiguration.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/OIDFederationEntityConfigurationProfileConfiguration.java
index 1460958e..fa05db09 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/OIDFederationEntityConfigurationProfileConfiguration.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/OIDFederationEntityConfigurationProfileConfiguration.java
@@ -33,7 +33,8 @@ import net.shibboleth.shared.annotation.constraint.Unmodifiable;
* Profile configuration for an OpenID Federation Entity Configuration.
*/
public interface OIDFederationEntityConfigurationProfileConfiguration extends OverriddenIssuerProfileConfiguration,
- OIDFederationProfileConfiguration, OIDFederationEntityStatementProducingProfileConfiguration {
+ OIDFederationProfileConfiguration, OIDFederationEntityStatementProducingProfileConfiguration,
+ OIDFederationResponseCachingProfileConfiguration{
/** OIDC base protocol URI. Section 4 is relevant. */
public static final String PROTOCOL_URI = "https://openid.net/specs/openid-federation-1_0.html";
@@ -64,17 +65,4 @@ public interface OIDFederationEntityConfigurationProfileConfiguration extends Ov
@ConfigurationSetting(name="entityStatementLifetime")
@Positive @Nonnull Duration getEntityStatementLifetime(@Nullable final ProfileRequestContext profileRequestContext);
- /**
- * Get cached entity statement lifetime.
- *
- * <p>Defaults to 10 seconds.</p>
- *
- * @param profileRequestContext profile request context
- *
- * @return cached entity statement lifetime
- */
- @ConfigurationSetting(name="cachedEntityStatementLifetime")
- @Positive @Nonnull
- Duration getCachedEntityStatementLifetime(@Nullable final ProfileRequestContext profileRequestContext);
-
}
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/OIDFederationResolveEntityProfileConfiguration.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/OIDFederationResolveEntityProfileConfiguration.java
index f5afddaa..6aaac8c8 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/OIDFederationResolveEntityProfileConfiguration.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/OIDFederationResolveEntityProfileConfiguration.java
@@ -29,7 +29,7 @@ import net.shibboleth.shared.annotation.constraint.Positive;
* Profile configuration for an OpenID Federation Resolve Entity.
*/
public interface OIDFederationResolveEntityProfileConfiguration extends OverriddenIssuerProfileConfiguration,
- OIDFederationProfileConfiguration {
+ OIDFederationProfileConfiguration, OIDFederationResponseCachingProfileConfiguration {
/** OIDC base protocol URI. */
public static final String PROTOCOL_URI = "https://openid.net/specs/openid-federation-1_0.html";
@@ -37,19 +37,6 @@ public interface OIDFederationResolveEntityProfileConfiguration extends Overridd
/** ID for this profile configuration. */
public static final String PROFILE_ID = "http://shibboleth.net/ns/profiles/oidfed/resolve-entity";
- /**
- * Get cached success response lifetime.
- *
- * <p>Defaults to 5 minutes.</p>
- *
- * @param profileRequestContext profile request context
- *
- * @return cached success response lifetime
- */
- @ConfigurationSetting(name="cachedSuccessResponseLifetime")
- @Positive @Nonnull
- Duration getCachedSuccessResponseLifetime(@Nullable final ProfileRequestContext profileRequestContext);
-
/**
* Get cached error response lifetime.
*
@@ -62,5 +49,4 @@ public interface OIDFederationResolveEntityProfileConfiguration extends Overridd
@ConfigurationSetting(name="cachedErrorResponseLifetime")
@Positive @Nonnull
Duration getCachedErrorResponseLifetime(@Nullable final ProfileRequestContext profileRequestContext);
-
}
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/OIDFederationResolveEntityProfileConfiguration.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/OIDFederationResponseCachingProfileConfiguration.java
similarity index 62%
copy from idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/OIDFederationResolveEntityProfileConfiguration.java
copy to idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/OIDFederationResponseCachingProfileConfiguration.java
index f5afddaa..5a0f143e 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/OIDFederationResolveEntityProfileConfiguration.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/config/OIDFederationResponseCachingProfileConfiguration.java
@@ -26,17 +26,11 @@ import net.shibboleth.shared.annotation.ConfigurationSetting;
import net.shibboleth.shared.annotation.constraint.Positive;
/**
- * Profile configuration for an OpenID Federation Resolve Entity.
+ * Common interface for OpenID Federation Profiles producing cacheable response messages.
*/
-public interface OIDFederationResolveEntityProfileConfiguration extends OverriddenIssuerProfileConfiguration,
+public interface OIDFederationResponseCachingProfileConfiguration extends OverriddenIssuerProfileConfiguration,
OIDFederationProfileConfiguration {
- /** OIDC base protocol URI. */
- public static final String PROTOCOL_URI = "https://openid.net/specs/openid-federation-1_0.html";
-
- /** ID for this profile configuration. */
- public static final String PROFILE_ID = "http://shibboleth.net/ns/profiles/oidfed/resolve-entity";
-
/**
* Get cached success response lifetime.
*
@@ -50,17 +44,4 @@ public interface OIDFederationResolveEntityProfileConfiguration extends Overridd
@Positive @Nonnull
Duration getCachedSuccessResponseLifetime(@Nullable final ProfileRequestContext profileRequestContext);
- /**
- * Get cached error response lifetime.
- *
- * <p>Defaults to 5 minutes.</p>
- *
- * @param profileRequestContext profile request context
- *
- * @return cached error response lifetime
- */
- @ConfigurationSetting(name="cachedErrorResponseLifetime")
- @Positive @Nonnull
- Duration getCachedErrorResponseLifetime(@Nullable final ProfileRequestContext profileRequestContext);
-
}
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultEntityConfigurationResponseContainerExpirationTimeStrategy.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultEntityConfigurationResponseContainerExpirationTimeStrategy.java
new file mode 100644
index 00000000..b0058b50
--- /dev/null
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultEntityConfigurationResponseContainerExpirationTimeStrategy.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;
+
+import java.time.Instant;
+import java.util.Optional;
+import java.util.function.Function;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
+
+import com.nimbusds.openid.connect.sdk.federation.config.FederationEntityConfigurationSuccessResponse;
+
+import net.shibboleth.oidc.metadata.cache.ExpirationTimeContext;
+
+/**
+ * Default strategy for fetching expiration time for the entity configuration response container. The expiration instant
+ * is fetched from which is before: the success response message's JWT expiration time or the instant returned by
+ * {@link NimbusResponseContainer#getExpirationInstant()}.
+ */
+ at ThreadSafe
+public class DefaultEntityConfigurationResponseContainerExpirationTimeStrategy
+ implements Function<ExpirationTimeContext<NimbusResponseContainer>, Instant> {
+
+ /** {@inheritDoc} */
+ @Nullable public Instant apply(@Nullable final ExpirationTimeContext<NimbusResponseContainer> context) {
+ if (context == null) {
+ return null;
+ }
+ final Instant contextExpiration = context.getNow().plus(context.getMaxCacheDuration());
+ final NimbusResponseContainer container = context.getMetadata();
+ if (container == null || container.getExpirationInstant() == null) {
+ return contextExpiration;
+ }
+ final Instant containerExpiration = container.getExpirationInstant();
+ if (container.getResponse() instanceof FederationEntityConfigurationSuccessResponse successResponse) {
+ final Instant jwtExpiration = Optional.ofNullable(
+ successResponse.getEntityStatement().getClaimsSet().getExpirationTime())
+ .map(date -> date.toInstant())
+ .orElse(null);
+ return jwtExpiration == null ? containerExpiration :
+ jwtExpiration.isBefore(containerExpiration) ? jwtExpiration : containerExpiration;
+ }
+ return containerExpiration;
+ }
+
+}
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultResolveEntityResponseFetchingStrategy.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultEntityConfigurationResponseFetchingStrategy.java
similarity index 58%
copy from idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultResolveEntityResponseFetchingStrategy.java
copy to idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultEntityConfigurationResponseFetchingStrategy.java
index 13270d4f..1862386b 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultResolveEntityResponseFetchingStrategy.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultEntityConfigurationResponseFetchingStrategy.java
@@ -27,39 +27,33 @@ import net.shibboleth.shared.primitive.LoggerFactory;
import net.shibboleth.shared.resolver.CriteriaSet;
/**
- * Default strategy for fetching resolve entity response container via criteria.
+ * Default strategy for fetching entity configuration response container via criteria.
*/
@ThreadSafeAfterInit
-public class DefaultResolveEntityResponseFetchingStrategy extends AbstractIdentifiableInitializableComponent
- implements Function<CriteriaSet, ResolveEntityResponseContainer> {
+public class DefaultEntityConfigurationResponseFetchingStrategy extends AbstractIdentifiableInitializableComponent
+ implements Function<CriteriaSet, NimbusResponseContainer> {
/** Class logger. */
- @Nonnull private Logger log = LoggerFactory.getLogger(DefaultResolveEntityResponseFetchingStrategy.class);
+ @Nonnull private Logger log = LoggerFactory.getLogger(DefaultEntityConfigurationResponseFetchingStrategy.class);
/** {@inheritDoc} */
@Override @Nullable
- public ResolveEntityResponseContainer apply(@Nullable final CriteriaSet criteria) {
+ public NimbusResponseContainer apply(@Nullable final CriteriaSet criteria) {
checkComponentActive();
if (criteria == null) {
return null;
}
- final ResolveEntityRequestCriterion requestCriterion = criteria.get(ResolveEntityRequestCriterion.class);
- if (requestCriterion == null) {
- log.debug("No request criterion given, returning null");
- return null;
- }
- final ResolveEntityResponseCriterion responseCriterion = criteria.get(ResolveEntityResponseCriterion.class);
+ final NimbusResponseCriterion responseCriterion = criteria.get(NimbusResponseCriterion.class);
if (responseCriterion == null) {
log.debug("No response criterion given, returning null");
return null;
}
- final ResolveEntityContainerExpirationCriterion expirationCriterion =
- criteria.get(ResolveEntityContainerExpirationCriterion.class);
+ final ResponseContainerExpirationCriterion expirationCriterion =
+ criteria.get(ResponseContainerExpirationCriterion.class);
if (expirationCriterion == null) {
log.debug("No expiration criterion given, returning null");
return null;
}
- return new ResolveEntityResponseContainer(responseCriterion.getResponse(), requestCriterion.getRequest(),
- expirationCriterion.getExpirationInstant());
+ return new NimbusResponseContainer(responseCriterion.getResponse(), expirationCriterion.getExpirationInstant());
}
}
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultResolveEntityResponseFetchingStrategy.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultResolveEntityResponseFetchingStrategy.java
index 13270d4f..70ba1cc8 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultResolveEntityResponseFetchingStrategy.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultResolveEntityResponseFetchingStrategy.java
@@ -48,13 +48,13 @@ public class DefaultResolveEntityResponseFetchingStrategy extends AbstractIdenti
log.debug("No request criterion given, returning null");
return null;
}
- final ResolveEntityResponseCriterion responseCriterion = criteria.get(ResolveEntityResponseCriterion.class);
+ final NimbusResponseCriterion responseCriterion = criteria.get(NimbusResponseCriterion.class);
if (responseCriterion == null) {
log.debug("No response criterion given, returning null");
return null;
}
- final ResolveEntityContainerExpirationCriterion expirationCriterion =
- criteria.get(ResolveEntityContainerExpirationCriterion.class);
+ final ResponseContainerExpirationCriterion expirationCriterion =
+ criteria.get(ResponseContainerExpirationCriterion.class);
if (expirationCriterion == null) {
log.debug("No expiration criterion given, returning null");
return null;
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponseContainer.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/NimbusResponseContainer.java
similarity index 64%
copy from idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponseContainer.java
copy to idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/NimbusResponseContainer.java
index 1ae9856f..9928613a 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponseContainer.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/NimbusResponseContainer.java
@@ -21,23 +21,19 @@ import javax.annotation.Nonnull;
import com.nimbusds.oauth2.sdk.Response;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.ResolveEntityRequest;
import net.shibboleth.shared.logic.Constraint;
/**
- * A container class for metadata caches carrying request and response message details related to Resolve Entity API.
+ * A container class for metadata caches carrying Nimbus response message.
*/
-public class ResolveEntityResponseContainer implements Serializable {
+public class NimbusResponseContainer implements Serializable {
/** Serial version UID. */
- private static final long serialVersionUID = 756269369356865370L;
+ private static final long serialVersionUID = 656269369356865370L;
/** Response message. */
@Nonnull private final Response response;
- /** Request message. */
- @Nonnull private final ResolveEntityRequest request;
-
/** Expiration instant for this container. */
@Nonnull private final Instant expiration;
@@ -45,13 +41,11 @@ public class ResolveEntityResponseContainer implements Serializable {
* Constructor.
*
* @param responseMessage response message
- * @param requestMessage request message
* @param expirationInstant expiration instant
*/
- public ResolveEntityResponseContainer(@Nonnull final Response responseMessage,
- @Nonnull final ResolveEntityRequest requestMessage, @Nonnull final Instant expirationInstant) {
+ public NimbusResponseContainer(@Nonnull final Response responseMessage,
+ @Nonnull final Instant expirationInstant) {
response = Constraint.isNotNull(responseMessage, "Response message cannot be null");
- request = Constraint.isNotNull(requestMessage, "Request message cannot be null");
expiration = Constraint.isNotNull(expirationInstant, "Expiration instant cannot be null");
}
@@ -64,15 +58,6 @@ public class ResolveEntityResponseContainer implements Serializable {
return response;
}
- /**
- * Get request message.
- *
- * @return request message
- */
- public ResolveEntityRequest getRequest() {
- return request;
- }
-
/**
* Get expiration instant.
*
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponseCriterion.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/NimbusResponseCriterion.java
similarity index 81%
rename from idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponseCriterion.java
rename to idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/NimbusResponseCriterion.java
index 43691690..bcc0dcda 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponseCriterion.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/NimbusResponseCriterion.java
@@ -24,9 +24,9 @@ import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.resolver.Criterion;
/**
- * A {@link Criterion} representing response message to a resolve entity request.
+ * A {@link Criterion} carrying Nimbus response message.
*/
-public class ResolveEntityResponseCriterion implements Criterion {
+public class NimbusResponseCriterion implements Criterion {
/** The response message. */
@Nonnull private final Response response;
@@ -36,7 +36,7 @@ public class ResolveEntityResponseCriterion implements Criterion {
*
* @param responseMessage response message, must not be null
*/
- public ResolveEntityResponseCriterion(@Nonnull final Response responseMessage) {
+ public NimbusResponseCriterion(@Nonnull final Response responseMessage) {
response = Constraint.isNotNull(responseMessage, "Response cannot be null");
}
@@ -52,7 +52,7 @@ public class ResolveEntityResponseCriterion implements Criterion {
/** {@inheritDoc} */
@Override
public String toString() {
- return "ResolveEntityResponseCriterion [response=" + response + "]";
+ return "NimbusResponseCriterion [response=" + response + "]";
}
/** {@inheritDoc} */
@@ -73,7 +73,7 @@ public class ResolveEntityResponseCriterion implements Criterion {
if (getClass() != obj.getClass()) {
return false;
}
- final ResolveEntityResponseCriterion other = (ResolveEntityResponseCriterion) obj;
+ final NimbusResponseCriterion other = (NimbusResponseCriterion) obj;
return response.equals(other.response);
}
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponseContainer.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponseContainer.java
index 1ae9856f..103a436a 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponseContainer.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponseContainer.java
@@ -27,20 +27,14 @@ import net.shibboleth.shared.logic.Constraint;
/**
* A container class for metadata caches carrying request and response message details related to Resolve Entity API.
*/
-public class ResolveEntityResponseContainer implements Serializable {
+public class ResolveEntityResponseContainer extends NimbusResponseContainer implements Serializable {
/** Serial version UID. */
private static final long serialVersionUID = 756269369356865370L;
- /** Response message. */
- @Nonnull private final Response response;
-
/** Request message. */
@Nonnull private final ResolveEntityRequest request;
- /** Expiration instant for this container. */
- @Nonnull private final Instant expiration;
-
/**
* Constructor.
*
@@ -50,18 +44,8 @@ public class ResolveEntityResponseContainer implements Serializable {
*/
public ResolveEntityResponseContainer(@Nonnull final Response responseMessage,
@Nonnull final ResolveEntityRequest requestMessage, @Nonnull final Instant expirationInstant) {
- response = Constraint.isNotNull(responseMessage, "Response message cannot be null");
+ super(responseMessage, expirationInstant);
request = Constraint.isNotNull(requestMessage, "Request message cannot be null");
- expiration = Constraint.isNotNull(expirationInstant, "Expiration instant cannot be null");
- }
-
- /**
- * Get response message.
- *
- * @return response message
- */
- public Response getResponse() {
- return response;
}
/**
@@ -73,13 +57,4 @@ public class ResolveEntityResponseContainer implements Serializable {
return request;
}
- /**
- * Get expiration instant.
- *
- * @return expiration instant
- */
- public Instant getExpirationInstant() {
- return expiration;
- }
-
}
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityContainerExpirationCriterion.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResponseContainerExpirationCriterion.java
similarity index 86%
rename from idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityContainerExpirationCriterion.java
rename to idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResponseContainerExpirationCriterion.java
index 83888cab..a969761f 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityContainerExpirationCriterion.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResponseContainerExpirationCriterion.java
@@ -23,9 +23,9 @@ import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.resolver.Criterion;
/**
- * A {@link Criterion} representing expiration instant for a resolve entity container.
+ * A {@link Criterion} representing expiration instant for a response message container.
*/
-public class ResolveEntityContainerExpirationCriterion implements Criterion {
+public class ResponseContainerExpirationCriterion implements Criterion {
/** The expiration instant. */
@Nonnull private final Instant instant;
@@ -35,7 +35,7 @@ public class ResolveEntityContainerExpirationCriterion implements Criterion {
*
* @param expirationInstant expiration instant, must not be null
*/
- public ResolveEntityContainerExpirationCriterion(@Nonnull final Instant expirationInstant) {
+ public ResponseContainerExpirationCriterion(@Nonnull final Instant expirationInstant) {
instant = Constraint.isNotNull(expirationInstant, "Expiration instant cannot be null");
}
@@ -72,7 +72,7 @@ public class ResolveEntityContainerExpirationCriterion implements Criterion {
if (getClass() != obj.getClass()) {
return false;
}
- final ResolveEntityContainerExpirationCriterion other = (ResolveEntityContainerExpirationCriterion) obj;
+ final ResponseContainerExpirationCriterion other = (ResponseContainerExpirationCriterion) obj;
return instant.equals(other.instant);
}
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/BuildResolveEntityErrorResponseFromEvent.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/BuildResolveEntityErrorResponseFromEvent.java
index 3562968f..e0117b32 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/BuildResolveEntityErrorResponseFromEvent.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/BuildResolveEntityErrorResponseFromEvent.java
@@ -29,12 +29,12 @@ import org.slf4j.Logger;
import com.nimbusds.oauth2.sdk.ErrorObject;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.config.ResolveEntityCachedErrorResponseLifetimeLookupFunction;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.config.CachedErrorResponseLifetimeLookupFunction;
import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.ResolveEntityRequest;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityContainerExpirationCriterion;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResponseContainerExpirationCriterion;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityRequestCriterion;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityResponseContainer;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityResponseCriterion;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.NimbusResponseCriterion;
import net.shibboleth.idp.plugin.oidc.op.profile.impl.AbstractBuildErrorResponseFromEvent;
import net.shibboleth.oidc.metadata.cache.MetadataCache;
import net.shibboleth.oidc.metadata.cache.MetadataCacheException;
@@ -47,7 +47,7 @@ import net.shibboleth.shared.resolver.CriteriaSet;
/**
* This action reads an event from the configured {@link EventContext} lookup strategy, constructs a JSON error response
- * message and attaches it as the outbound message. If {@link RelyingPartyResolveEntityContext} is found, it's exploited
+ * message and attaches it as the outbound message. If {@link RelyingPartyCachedMessageContext} is found, it's exploited
* for storing the response message in the configured {@link #responseCache}.
*/
public class BuildResolveEntityErrorResponseFromEvent extends AbstractBuildErrorResponseFromEvent<JSONErrorResponse> {
@@ -63,15 +63,15 @@ public class BuildResolveEntityErrorResponseFromEvent extends AbstractBuildError
/** Strategy used to locate the resolve entity context. */
@Nonnull
- private Function<ProfileRequestContext, RelyingPartyResolveEntityContext> resolveEntityContextLookupStrategy;
+ private Function<ProfileRequestContext, RelyingPartyCachedMessageContext> resolveEntityContextLookupStrategy;
/**
* Constructor.
*/
public BuildResolveEntityErrorResponseFromEvent() {
- cachedResponseLifetimeLookupStrategy = new ResolveEntityCachedErrorResponseLifetimeLookupFunction();
- final Function<ProfileRequestContext, RelyingPartyResolveEntityContext> recls =
- new ChildContextLookup<>(RelyingPartyResolveEntityContext.class).compose(
+ cachedResponseLifetimeLookupStrategy = new CachedErrorResponseLifetimeLookupFunction();
+ final Function<ProfileRequestContext, RelyingPartyCachedMessageContext> recls =
+ new ChildContextLookup<>(RelyingPartyCachedMessageContext.class).compose(
new InboundMessageContextLookup());
assert recls != null;
resolveEntityContextLookupStrategy = recls;
@@ -105,7 +105,7 @@ public class BuildResolveEntityErrorResponseFromEvent extends AbstractBuildError
* @param strategy What to set.
*/
public void setResolveEntityContextLookupStrategy(
- @Nonnull final Function<ProfileRequestContext,RelyingPartyResolveEntityContext> strategy) {
+ @Nonnull final Function<ProfileRequestContext,RelyingPartyCachedMessageContext> strategy) {
checkSetterPreconditions();
resolveEntityContextLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null!");
}
@@ -125,19 +125,19 @@ public class BuildResolveEntityErrorResponseFromEvent extends AbstractBuildError
protected JSONErrorResponse buildErrorResponse(final ErrorObject error,
final ProfileRequestContext profileRequestContext) {
final JSONErrorResponse response = new JSONErrorResponse(error);
- final RelyingPartyResolveEntityContext resolveEntityContext =
+ final RelyingPartyCachedMessageContext resolveEntityContext =
resolveEntityContextLookupStrategy.apply(profileRequestContext);
- if (resolveEntityContext != null && resolveEntityContext.getValidatedRequest() != null) {
- final ResolveEntityResponseCriterion responseCriterion = new ResolveEntityResponseCriterion(response);
+ if (resolveEntityContext != null &&
+ resolveEntityContext.getValidatedRequest() instanceof ResolveEntityRequest resolveEntityRequest) {
+ final NimbusResponseCriterion responseCriterion = new NimbusResponseCriterion(response);
final Duration cachedResponseLifetime = cachedResponseLifetimeLookupStrategy.apply(profileRequestContext);
final Instant expiration = Instant.now().plus(cachedResponseLifetime);
assert expiration != null;
- final ResolveEntityContainerExpirationCriterion expirationCriterion =
- new ResolveEntityContainerExpirationCriterion(expiration);
- final ResolveEntityRequest validatedRequest = resolveEntityContext.getValidatedRequest();
- assert validatedRequest != null;
- final ResolveEntityRequestCriterion requestCriterion = new ResolveEntityRequestCriterion(validatedRequest);
+ final ResponseContainerExpirationCriterion expirationCriterion =
+ new ResponseContainerExpirationCriterion(expiration);
+ final ResolveEntityRequestCriterion requestCriterion =
+ new ResolveEntityRequestCriterion(resolveEntityRequest);
final CriteriaSet criteria = new CriteriaSet(requestCriterion, responseCriterion, expirationCriterion);
try {
final List<ResolveEntityResponseContainer> result = responseCache.get(criteria);
@@ -148,7 +148,7 @@ public class BuildResolveEntityErrorResponseFromEvent extends AbstractBuildError
log.debug("{} Response stored into the cache", getLogPrefix());
}
} catch (final MetadataCacheException e) {
- log.error("{} Could not store the response record into tht metadata cache", getLogPrefix(), e);
+ log.error("{} Could not store the response record into the metadata cache", getLogPrefix(), e);
}
}
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/FormOutboundFederationConfigurationResponse.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/FormOutboundFederationConfigurationResponse.java
index 635ece0f..226c971c 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/FormOutboundFederationConfigurationResponse.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/FormOutboundFederationConfigurationResponse.java
@@ -14,9 +14,9 @@
package net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl;
-import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
+import java.util.List;
import java.util.function.Function;
import javax.annotation.Nonnull;
@@ -27,20 +27,27 @@ import org.opensaml.profile.action.ActionSupport;
import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.profile.context.navigate.OutboundMessageContextLookup;
-import org.opensaml.storage.StorageService;
import org.slf4j.Logger;
import com.nimbusds.jwt.SignedJWT;
import com.nimbusds.oauth2.sdk.ParseException;
+import com.nimbusds.oauth2.sdk.Response;
import com.nimbusds.openid.connect.sdk.federation.config.FederationEntityConfigurationSuccessResponse;
import com.nimbusds.openid.connect.sdk.federation.entities.EntityStatement;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.config.OIDFederationEntityConfigurationProfileConfiguration;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.navigate.CachedEntityStatementLifetimeLookupFunction;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.config.CachedSuccessResponseLifetimeLookupFunction;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.NimbusResponseContainer;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.NimbusResponseCriterion;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResponseContainerExpirationCriterion;
import net.shibboleth.idp.profile.AbstractProfileAction;
+import net.shibboleth.oidc.metadata.cache.MetadataCache;
+import net.shibboleth.oidc.metadata.cache.MetadataCacheException;
import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
+import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.resolver.CriteriaSet;
/**
* This action builds a response for the OpenID federation configuration request. The response contains an
@@ -53,22 +60,36 @@ public class FormOutboundFederationConfigurationResponse extends AbstractProfile
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(FormOutboundFederationConfigurationResponse.class);
+ /** Metadata cache for cached response containers. */
+ @NonnullAfterInit private MetadataCache<NimbusResponseContainer> responseCache;
+
+ /** Strategy used to locate the cached message context. */
+ @Nonnull
+ private Function<ProfileRequestContext, RelyingPartyCachedMessageContext> cachedMessageContextLookupStrategy;
+
/** Strategy used to locate the subcontext to hold the statement. */
@Nonnull private Function<ProfileRequestContext,EntityStatementContext> entityStatementContextLookupStrategy;
- @Nonnull private Function<ProfileRequestContext,Duration> storageRecordLifetimeLookupStrategy;
- @NonnullAfterInit private StorageService storageService;
+ /** Strategy used to locate the lifetime for the cached response record. */
+ @Nonnull private Function<ProfileRequestContext,Duration> cachedResponseLifetimeLookupStrategy;
/** JWT used to build entity statement. */
@Nullable private SignedJWT jwt;
+ /** The resolve entity context to operate on. */
+ @NonnullBeforeExec private RelyingPartyCachedMessageContext cachedMessageContext;
+
+ /**
+ * Constructor.
+ */
public FormOutboundFederationConfigurationResponse() {
final Function<ProfileRequestContext,EntityStatementContext> escls =
new ChildContextLookup<>(EntityStatementContext.class).compose(
new OutboundMessageContextLookup());
assert escls != null;
entityStatementContextLookupStrategy = escls;
- storageRecordLifetimeLookupStrategy = new CachedEntityStatementLifetimeLookupFunction();
+ cachedMessageContextLookupStrategy = new ChildContextLookup<>(RelyingPartyCachedMessageContext.class);
+ cachedResponseLifetimeLookupStrategy = new CachedSuccessResponseLifetimeLookupFunction();
}
/**
@@ -76,14 +97,52 @@ public class FormOutboundFederationConfigurationResponse extends AbstractProfile
*
* @param strategy What to set.
*/
- public void setMetadataResolver(@Nonnull final Function<ProfileRequestContext,EntityStatementContext> strategy) {
+ public void setEntityStatementContextLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext,EntityStatementContext> strategy) {
checkSetterPreconditions();
entityStatementContextLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null!");
}
- public void setStorageService(@Nonnull final StorageService service) {
+ /**
+ * Set the strategy used to locate the cached message context
+ *
+ * @param strategy What to set.
+ */
+ public void setCachedMessageContextLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext,RelyingPartyCachedMessageContext> strategy) {
+ checkSetterPreconditions();
+ cachedMessageContextLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null!");
+ }
+
+ /**
+ * Set the metadata cache for cached response containers.
+ *
+ * @param cache What to set.
+ */
+ public void setResponseCache(@Nonnull final MetadataCache<NimbusResponseContainer> cache) {
+ checkSetterPreconditions();
+ responseCache = Constraint.isNotNull(cache, "Response metadata cache cannot be null");
+ }
+
+ /**
+ * Set the strategy used to locate the lifetime for the cached response record.
+ *
+ * @param strategy What to set.
+ */
+ public void setCachedResponseLifetimeLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext, Duration> strategy) {
checkSetterPreconditions();
- storageService = Constraint.isNotNull(service, "Storage service cannot be null!");
+ cachedResponseLifetimeLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+
+ if (responseCache == null) {
+ throw new ComponentInitializationException("Response metadata cache cannot be null");
+ }
}
/** {@inheritDoc} */
@@ -93,47 +152,74 @@ public class FormOutboundFederationConfigurationResponse extends AbstractProfile
if (!super.doPreExecute(profileRequestContext)) {
return false;
}
+ cachedMessageContext = cachedMessageContextLookupStrategy.apply(profileRequestContext);
+ if (cachedMessageContext == null) {
+ log.error("{} Could not resolve cached message context", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
+ return false;
+ }
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
+ final Response cachedResponse = cachedMessageContext.getCachedResponse();
+ if (cachedResponse != null) {
+ log.debug("{} Cached response found, storing in to the outbound message context", getLogPrefix());
+ profileRequestContext.ensureOutboundMessageContext().setMessage(cachedResponse);
+ return;
+ }
+ log.debug("{} No cached response found, resolving the response JWT from the context", getLogPrefix());
final EntityStatementContext entityStatementContext =
entityStatementContextLookupStrategy.apply(profileRequestContext);
if (entityStatementContext == null) {
log.error("{} Could not resolve entity statement context", getLogPrefix());
ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
- return false;
+ return;
}
if (entityStatementContext.getJWT() instanceof SignedJWT signedJwt) {
jwt = signedJwt;
} else {
log.error("{} No signed JWT found from the entity statement context", getLogPrefix());
ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
- return false;
+ return;
}
- return true;
- }
-
- /** {@inheritDoc} */
- @Override
- protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
- final EntityStatement entityStatement;
+ assert jwt != null;
+ final FederationEntityConfigurationSuccessResponse response;
try {
- entityStatement = EntityStatement.parse(jwt);
+ response = new FederationEntityConfigurationSuccessResponse(EntityStatement.parse(jwt));
} catch (ParseException e) {
- log.error("{} Could not parse entity statement from JWT", getLogPrefix(), e);
+ log.error("{} No signed JWT found from the entity statement context", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
+ return;
+ }
+ final NimbusResponseCriterion responseCriterion = new NimbusResponseCriterion(response);
+ final Duration lifetime = cachedResponseLifetimeLookupStrategy.apply(profileRequestContext);
+ if (lifetime == null) {
+ log.error("{} Could not resolve lifetime for the cached response record", getLogPrefix());
ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
return;
}
- final Duration lifetime = storageRecordLifetimeLookupStrategy.apply(profileRequestContext);
- final FederationEntityConfigurationSuccessResponse response =
- new FederationEntityConfigurationSuccessResponse(entityStatement);
+ final Instant expiration = Instant.now().plus(lifetime);
+ assert expiration != null;
+ final ResponseContainerExpirationCriterion expirationCriterion =
+ new ResponseContainerExpirationCriterion(expiration);
+ final CriteriaSet criteria = new CriteriaSet(responseCriterion, expirationCriterion);
try {
- assert jwt != null;
- final String serializedJwt = jwt.serialize();
- assert serializedJwt != null;
- storageService.create(OIDFederationEntityConfigurationProfileConfiguration.PROFILE_ID, "entityStatement", serializedJwt, Instant.now().plus(lifetime).toEpochMilli());
- } catch (final IOException e) {
- log.warn("{} Could not store the entity statement into storage service", getLogPrefix(), e);
+ final List<NimbusResponseContainer> result = responseCache.get(criteria);
+ if (result.size() != 1) {
+ log.error("{} Unexpected result (size={}) when storing response record into the metadata cache",
+ getLogPrefix(), result.size());
+ } else {
+ log.debug("{} Response stored into the cache", getLogPrefix());
+ }
+ } catch (final MetadataCacheException e) {
+ log.error("{} Could not store the response record into tht metadata cache", getLogPrefix(), e);
}
- log.debug("{} Response stored into the cache", getLogPrefix());
+
profileRequestContext.ensureOutboundMessageContext().setMessage(response);
}
}
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/FormOutboundResolveEntityResponse.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/FormOutboundResolveEntityResponse.java
index ccdc1d8b..86cd0b89 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/FormOutboundResolveEntityResponse.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/FormOutboundResolveEntityResponse.java
@@ -33,13 +33,13 @@ import com.nimbusds.jwt.SignedJWT;
import com.nimbusds.oauth2.sdk.Response;
import com.nimbusds.openid.connect.sdk.federation.entities.EntityStatement;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.config.ResolveEntityCachedSuccessResponseLifetimeLookupFunction;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.config.CachedSuccessResponseLifetimeLookupFunction;
import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.ResolveEntityRequest;
import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.ResolveEntityResponse;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityContainerExpirationCriterion;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResponseContainerExpirationCriterion;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityRequestCriterion;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityResponseContainer;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityResponseCriterion;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.NimbusResponseCriterion;
import net.shibboleth.idp.profile.AbstractProfileAction;
import net.shibboleth.oidc.metadata.cache.MetadataCache;
import net.shibboleth.oidc.metadata.cache.MetadataCacheException;
@@ -67,7 +67,7 @@ public class FormOutboundResolveEntityResponse extends AbstractProfileAction {
/** Strategy used to locate the resolve entity context. */
@Nonnull
- private Function<ProfileRequestContext, RelyingPartyResolveEntityContext> resolveEntityContextLookupStrategy;
+ private Function<ProfileRequestContext, RelyingPartyCachedMessageContext> cachedMessageContextLookupStrategy;
/** Strategy used to locate the subcontext to hold the statement. */
@Nonnull private Function<ProfileRequestContext,EntityStatementContext> entityStatementContextLookupStrategy;
@@ -79,7 +79,7 @@ public class FormOutboundResolveEntityResponse extends AbstractProfileAction {
@NonnullBeforeExec private SignedJWT jwt;
/** The resolve entity context to operate on. */
- @NonnullBeforeExec private RelyingPartyResolveEntityContext resolveEntityContext;
+ @NonnullBeforeExec private RelyingPartyCachedMessageContext cachedMessageContext;
/**
* Constructor.
@@ -90,12 +90,12 @@ public class FormOutboundResolveEntityResponse extends AbstractProfileAction {
new OutboundMessageContextLookup());
assert escls != null;
entityStatementContextLookupStrategy = escls;
- final Function<ProfileRequestContext, RelyingPartyResolveEntityContext> recls =
- new ChildContextLookup<>(RelyingPartyResolveEntityContext.class).compose(
+ final Function<ProfileRequestContext, RelyingPartyCachedMessageContext> recls =
+ new ChildContextLookup<>(RelyingPartyCachedMessageContext.class).compose(
new InboundMessageContextLookup());
assert recls != null;
- resolveEntityContextLookupStrategy = recls;
- cachedResponseLifetimeLookupStrategy = new ResolveEntityCachedSuccessResponseLifetimeLookupFunction();
+ cachedMessageContextLookupStrategy = recls;
+ cachedResponseLifetimeLookupStrategy = new CachedSuccessResponseLifetimeLookupFunction();
}
/**
@@ -110,14 +110,14 @@ public class FormOutboundResolveEntityResponse extends AbstractProfileAction {
}
/**
- * Set the strategy used to locate the resolve entity context
+ * Set the strategy used to locate the cached message context
*
* @param strategy What to set.
*/
- public void setResolveEntityContextLookupStrategy(
- @Nonnull final Function<ProfileRequestContext,RelyingPartyResolveEntityContext> strategy) {
+ public void setCachedMessageContextLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext,RelyingPartyCachedMessageContext> strategy) {
checkSetterPreconditions();
- resolveEntityContextLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null!");
+ cachedMessageContextLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null!");
}
/**
@@ -158,9 +158,9 @@ public class FormOutboundResolveEntityResponse extends AbstractProfileAction {
if (!super.doPreExecute(profileRequestContext)) {
return false;
}
- resolveEntityContext = resolveEntityContextLookupStrategy.apply(profileRequestContext);
- if (resolveEntityContext == null) {
- log.error("{} Could not resolve resolve entity context", getLogPrefix());
+ cachedMessageContext = cachedMessageContextLookupStrategy.apply(profileRequestContext);
+ if (cachedMessageContext == null) {
+ log.error("{} Could not resolve cached message context", getLogPrefix());
ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
return false;
}
@@ -171,7 +171,7 @@ public class FormOutboundResolveEntityResponse extends AbstractProfileAction {
/** {@inheritDoc} */
@Override
protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
- final Response cachedResponse = resolveEntityContext.getCachedResponse();
+ final Response cachedResponse = cachedMessageContext.getCachedResponse();
if (cachedResponse != null) {
log.debug("{} Cached response found, storing in to the outbound message context", getLogPrefix());
profileRequestContext.ensureOutboundMessageContext().setMessage(cachedResponse);
@@ -195,8 +195,7 @@ public class FormOutboundResolveEntityResponse extends AbstractProfileAction {
assert jwt != null;
final ResolveEntityResponse response = new ResolveEntityResponse(jwt);
- final ResolveEntityResponseCriterion responseCriterion = new ResolveEntityResponseCriterion(response);
- final ResolveEntityRequest validatedRequest = resolveEntityContext.getValidatedRequest();
+ final NimbusResponseCriterion responseCriterion = new NimbusResponseCriterion(response);
final Duration lifetime = cachedResponseLifetimeLookupStrategy.apply(profileRequestContext);
if (lifetime == null) {
log.error("{} Could not resolve lifetime for the cached response record", getLogPrefix());
@@ -205,26 +204,28 @@ public class FormOutboundResolveEntityResponse extends AbstractProfileAction {
}
final Instant expiration = Instant.now().plus(lifetime);
assert expiration != null;
- final ResolveEntityContainerExpirationCriterion expirationCriterion =
- new ResolveEntityContainerExpirationCriterion(expiration);
- if (validatedRequest == null) {
+ final ResponseContainerExpirationCriterion expirationCriterion =
+ new ResponseContainerExpirationCriterion(expiration);
+ if (cachedMessageContext.getValidatedRequest() instanceof ResolveEntityRequest validatedRequest) {
+ final ResolveEntityRequestCriterion requestCriterion = new ResolveEntityRequestCriterion(validatedRequest);
+ final CriteriaSet criteria = new CriteriaSet(requestCriterion, responseCriterion, expirationCriterion);
+ try {
+ final List<ResolveEntityResponseContainer> result = responseCache.get(criteria);
+ if (result.size() != 1) {
+ log.error("{} Unexpected result (size={}) when storing response record into the metadata cache",
+ getLogPrefix(), result.size());
+ } else {
+ log.debug("{} Response stored into the cache", getLogPrefix());
+ }
+ } catch (final MetadataCacheException e) {
+ log.error("{} Could not store the response record into tht metadata cache", getLogPrefix(), e);
+ }
+ } else {
log.error("{} No validated request found from the resolve entity context", getLogPrefix());
ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
return;
}
- final ResolveEntityRequestCriterion requestCriterion = new ResolveEntityRequestCriterion(validatedRequest);
- final CriteriaSet criteria = new CriteriaSet(requestCriterion, responseCriterion, expirationCriterion);
- try {
- final List<ResolveEntityResponseContainer> result = responseCache.get(criteria);
- if (result.size() != 1) {
- log.error("{} Unexpected result (size={}) when storing response record into the metadata cache",
- getLogPrefix(), result.size());
- } else {
- log.debug("{} Response stored into the cache", getLogPrefix());
- }
- } catch (final MetadataCacheException e) {
- log.error("{} Could not store the response record into tht metadata cache", getLogPrefix(), e);
- }
+
profileRequestContext.ensureOutboundMessageContext().setMessage(response);
}
}
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/LookupCachedResolveEntityRespomse.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/LookupCachedEntityConfigurationResponse.java
similarity index 55%
copy from idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/LookupCachedResolveEntityRespomse.java
copy to idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/LookupCachedEntityConfigurationResponse.java
index de2ebfbc..5b38b731 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/LookupCachedResolveEntityRespomse.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/LookupCachedEntityConfigurationResponse.java
@@ -23,12 +23,9 @@ import org.opensaml.messaging.context.navigate.ChildContextLookup;
import org.opensaml.profile.action.ActionSupport;
import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
import org.slf4j.Logger;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.ResolveEntityRequest;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityRequestCriterion;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityResponseContainer;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.NimbusResponseContainer;
import net.shibboleth.idp.profile.AbstractProfileAction;
import net.shibboleth.oidc.metadata.cache.MetadataCache;
import net.shibboleth.oidc.metadata.cache.MetadataCacheException;
@@ -40,53 +37,49 @@ import net.shibboleth.shared.primitive.LoggerFactory;
import net.shibboleth.shared.resolver.CriteriaSet;
/**
- * Lookup if a cached response already exists for the validated resolve entity API request. If yes, the response is
- * stored into {@link RelyingPartyResolveEntityContext} and a corresponding event ID is published.
+ * Lookup if a cached response already exists for entity configuration. If yes, the response is
+ * stored into {@link RelyingPartyCachedMessageContext} and a corresponding event ID is published.
*
* @event {@link EventIds#PROCEED_EVENT_ID}
* @event {@link EventIds#INVALID_PROFILE_CTX}
- * @event {@link OidFederationEventIds#CACHED_RESOLVE_ENTITY_RESPONSE}
+ * @event {@link OidFederationEventIds#CACHED_ENTITY_CONFIGURATION_RESPONSE}
*
* @since 4.3.0
*/
-public class LookupCachedResolveEntityRespomse extends AbstractProfileAction {
+public class LookupCachedEntityConfigurationResponse extends AbstractProfileAction {
/** Class logger. */
- @Nonnull private Logger log = LoggerFactory.getLogger(LookupCachedResolveEntityRespomse.class);
+ @Nonnull private Logger log = LoggerFactory.getLogger(LookupCachedEntityConfigurationResponse.class);
- /** Strategy used to locate the resolve entity context. */
+ /** Strategy used to create the cached message context. */
@Nonnull
- private Function<ProfileRequestContext, RelyingPartyResolveEntityContext> resolveEntityContextLookupStrategy;
+ private Function<ProfileRequestContext, RelyingPartyCachedMessageContext> cachedMessageContextCreationStrategy;
/** Metadata cache for cached response containers. */
- @NonnullAfterInit private MetadataCache<ResolveEntityResponseContainer> responseCache;
+ @NonnullAfterInit private MetadataCache<NimbusResponseContainer> responseCache;
- /** Trust chain context to operate on. */
- @NonnullBeforeExec private RelyingPartyResolveEntityContext resolveEntityContext;
-
- /** Request message to operate on. */
- @NonnullBeforeExec private ResolveEntityRequest validatedRequest;
+ /** Cached message context to operate on. */
+ @NonnullBeforeExec private RelyingPartyCachedMessageContext cachedMessageContext;
/**
* Constructor.
*/
- public LookupCachedResolveEntityRespomse() {
- final Function<ProfileRequestContext, RelyingPartyResolveEntityContext> recls =
- new ChildContextLookup<>(RelyingPartyResolveEntityContext.class).compose(
- new InboundMessageContextLookup());
+ public LookupCachedEntityConfigurationResponse() {
+ final Function<ProfileRequestContext, RelyingPartyCachedMessageContext> recls =
+ new ChildContextLookup<>(RelyingPartyCachedMessageContext.class, true);
assert recls != null;
- resolveEntityContextLookupStrategy = recls;
+ cachedMessageContextCreationStrategy = recls;
}
/**
- * Set the strategy used to locate the resolve entity context
+ * Set the strategy used to create the cached message context
*
* @param strategy What to set.
*/
- public void setResolveEntityContextLookupStrategy(
- @Nonnull final Function<ProfileRequestContext,RelyingPartyResolveEntityContext> strategy) {
+ public void setCachedMessageContextCreationStrategy(
+ @Nonnull final Function<ProfileRequestContext,RelyingPartyCachedMessageContext> strategy) {
checkSetterPreconditions();
- resolveEntityContextLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null!");
+ cachedMessageContextCreationStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null!");
}
/**
@@ -94,7 +87,7 @@ public class LookupCachedResolveEntityRespomse extends AbstractProfileAction {
*
* @param cache What to set.
*/
- public void setResponseCache(@Nonnull final MetadataCache<ResolveEntityResponseContainer> cache) {
+ public void setResponseCache(@Nonnull final MetadataCache<NimbusResponseContainer> cache) {
checkSetterPreconditions();
responseCache = Constraint.isNotNull(cache, "Response metadata cache cannot be null");
}
@@ -115,33 +108,31 @@ public class LookupCachedResolveEntityRespomse extends AbstractProfileAction {
return false;
}
- resolveEntityContext = resolveEntityContextLookupStrategy.apply(profileRequestContext);
- if (resolveEntityContext == null || resolveEntityContext.getValidatedRequest() == null) {
- log.error("{} Could not resolve validated resolve entity request", getLogPrefix());
+ cachedMessageContext = cachedMessageContextCreationStrategy.apply(profileRequestContext);
+ if (cachedMessageContext == null) {
+ log.error("{} Could not create cached response context", getLogPrefix());
ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
return false;
}
- validatedRequest = resolveEntityContext.getValidatedRequest();
-
+
return true;
}
/** {@inheritDoc} */
@Override
protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
- assert validatedRequest != null;
- final ResolveEntityRequestCriterion requestCriterion = new ResolveEntityRequestCriterion(validatedRequest);
- final CriteriaSet criteria = new CriteriaSet(requestCriterion);
+ final CriteriaSet criteria = new CriteriaSet();
try {
- final List<ResolveEntityResponseContainer> result = responseCache.get(criteria);
+ final List<NimbusResponseContainer> result = responseCache.get(criteria);
if (result.size() != 1) {
log.debug("{} No cached response record found from the metadata cache", getLogPrefix(), result.size());
} else {
- final ResolveEntityResponseContainer cachedResponse = result.get(0);
- resolveEntityContext.setCachedResponse(cachedResponse.getResponse());
+ final NimbusResponseContainer cachedResponse = result.get(0);
+ cachedMessageContext.setCachedResponse(cachedResponse.getResponse());
log.debug("{} Response found from the cache, publishing event {}", getLogPrefix(),
- OidFederationEventIds.CACHED_RESOLVE_ENTITY_RESPONSE);
- ActionSupport.buildEvent(profileRequestContext, OidFederationEventIds.CACHED_RESOLVE_ENTITY_RESPONSE);
+ OidFederationEventIds.CACHED_ENTITY_CONFIGURATION_RESPONSE);
+ ActionSupport.buildEvent(profileRequestContext,
+ OidFederationEventIds.CACHED_ENTITY_CONFIGURATION_RESPONSE);
return;
}
} catch (final MetadataCacheException e) {
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/LookupCachedResolveEntityRespomse.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/LookupCachedResolveEntityResponse.java
similarity index 77%
rename from idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/LookupCachedResolveEntityRespomse.java
rename to idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/LookupCachedResolveEntityResponse.java
index de2ebfbc..1701d69a 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/LookupCachedResolveEntityRespomse.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/LookupCachedResolveEntityResponse.java
@@ -41,7 +41,7 @@ import net.shibboleth.shared.resolver.CriteriaSet;
/**
* Lookup if a cached response already exists for the validated resolve entity API request. If yes, the response is
- * stored into {@link RelyingPartyResolveEntityContext} and a corresponding event ID is published.
+ * stored into {@link RelyingPartyCachedMessageContext} and a corresponding event ID is published.
*
* @event {@link EventIds#PROCEED_EVENT_ID}
* @event {@link EventIds#INVALID_PROFILE_CTX}
@@ -49,20 +49,20 @@ import net.shibboleth.shared.resolver.CriteriaSet;
*
* @since 4.3.0
*/
-public class LookupCachedResolveEntityRespomse extends AbstractProfileAction {
+public class LookupCachedResolveEntityResponse extends AbstractProfileAction {
/** Class logger. */
- @Nonnull private Logger log = LoggerFactory.getLogger(LookupCachedResolveEntityRespomse.class);
+ @Nonnull private Logger log = LoggerFactory.getLogger(LookupCachedResolveEntityResponse.class);
- /** Strategy used to locate the resolve entity context. */
+ /** Strategy used to locate the cached message context. */
@Nonnull
- private Function<ProfileRequestContext, RelyingPartyResolveEntityContext> resolveEntityContextLookupStrategy;
+ private Function<ProfileRequestContext, RelyingPartyCachedMessageContext> cachedMessageContextLookupStrategy;
/** Metadata cache for cached response containers. */
@NonnullAfterInit private MetadataCache<ResolveEntityResponseContainer> responseCache;
- /** Trust chain context to operate on. */
- @NonnullBeforeExec private RelyingPartyResolveEntityContext resolveEntityContext;
+ /** Cached message context to operate on. */
+ @NonnullBeforeExec private RelyingPartyCachedMessageContext cachedMessageContext;
/** Request message to operate on. */
@NonnullBeforeExec private ResolveEntityRequest validatedRequest;
@@ -70,23 +70,23 @@ public class LookupCachedResolveEntityRespomse extends AbstractProfileAction {
/**
* Constructor.
*/
- public LookupCachedResolveEntityRespomse() {
- final Function<ProfileRequestContext, RelyingPartyResolveEntityContext> recls =
- new ChildContextLookup<>(RelyingPartyResolveEntityContext.class).compose(
+ public LookupCachedResolveEntityResponse() {
+ final Function<ProfileRequestContext, RelyingPartyCachedMessageContext> recls =
+ new ChildContextLookup<>(RelyingPartyCachedMessageContext.class).compose(
new InboundMessageContextLookup());
assert recls != null;
- resolveEntityContextLookupStrategy = recls;
+ cachedMessageContextLookupStrategy = recls;
}
/**
- * Set the strategy used to locate the resolve entity context
+ * Set the strategy used to locate the cached message context
*
* @param strategy What to set.
*/
- public void setResolveEntityContextLookupStrategy(
- @Nonnull final Function<ProfileRequestContext,RelyingPartyResolveEntityContext> strategy) {
+ public void setCachedMessageContextLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext,RelyingPartyCachedMessageContext> strategy) {
checkSetterPreconditions();
- resolveEntityContextLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null!");
+ cachedMessageContextLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null!");
}
/**
@@ -115,13 +115,20 @@ public class LookupCachedResolveEntityRespomse extends AbstractProfileAction {
return false;
}
- resolveEntityContext = resolveEntityContextLookupStrategy.apply(profileRequestContext);
- if (resolveEntityContext == null || resolveEntityContext.getValidatedRequest() == null) {
+ cachedMessageContext = cachedMessageContextLookupStrategy.apply(profileRequestContext);
+ if (cachedMessageContext == null) {
+ log.error("{} Could not resolve cached response context", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
+ return false;
+ }
+
+ if (cachedMessageContext.getValidatedRequest() instanceof ResolveEntityRequest resolveEntityRequest) {
+ validatedRequest = resolveEntityRequest;
+ } else {
log.error("{} Could not resolve validated resolve entity request", getLogPrefix());
ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
return false;
}
- validatedRequest = resolveEntityContext.getValidatedRequest();
return true;
}
@@ -138,7 +145,7 @@ public class LookupCachedResolveEntityRespomse extends AbstractProfileAction {
log.debug("{} No cached response record found from the metadata cache", getLogPrefix(), result.size());
} else {
final ResolveEntityResponseContainer cachedResponse = result.get(0);
- resolveEntityContext.setCachedResponse(cachedResponse.getResponse());
+ cachedMessageContext.setCachedResponse(cachedResponse.getResponse());
log.debug("{} Response found from the cache, publishing event {}", getLogPrefix(),
OidFederationEventIds.CACHED_RESOLVE_ENTITY_RESPONSE);
ActionSupport.buildEvent(profileRequestContext, OidFederationEventIds.CACHED_RESOLVE_ENTITY_RESPONSE);
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/OidFederationEventIds.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/OidFederationEventIds.java
index 1f3e9f4f..2558d9fa 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/OidFederationEventIds.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/OidFederationEventIds.java
@@ -34,6 +34,12 @@ public class OidFederationEventIds {
*/
@Nonnull @NotEmpty public static final String CACHED_RESOLVE_ENTITY_RESPONSE = "CachedResolveEntityResponseFound";
+ /**
+ * ID of event returned if cached entity configuration response was found and set to the context.
+ */
+ @Nonnull @NotEmpty public static final String CACHED_ENTITY_CONFIGURATION_RESPONSE =
+ "CachedEntityConfigurationResponseFound";
+
/**
* ID of event returned if the given trust anchor is invalid.
*/
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/RelyingPartyResolveEntityContext.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/RelyingPartyCachedMessageContext.java
similarity index 73%
rename from idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/RelyingPartyResolveEntityContext.java
rename to idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/RelyingPartyCachedMessageContext.java
index 0a86ab99..938485b2 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/RelyingPartyResolveEntityContext.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/RelyingPartyCachedMessageContext.java
@@ -19,19 +19,18 @@ import javax.annotation.Nullable;
import org.opensaml.messaging.context.BaseContext;
+import com.nimbusds.oauth2.sdk.Request;
import com.nimbusds.oauth2.sdk.Response;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.ResolveEntityRequest;
-
/**
- * Subcontext carrying information for resolve entity related to a relying party.
+ * Subcontext carrying information for request and response messages related to a relying party.
*
* @since 4.3.0
*/
-public final class RelyingPartyResolveEntityContext extends BaseContext {
+public final class RelyingPartyCachedMessageContext extends BaseContext {
- /** Validated (possibly modified) resolve entity request. */
- @Nullable private ResolveEntityRequest validatedRequest;
+ /** Validated (possibly modified) request message. */
+ @Nullable private Request validatedRequest;
/** Cached response message. */
@Nullable private Response cachedResponse;
@@ -41,7 +40,7 @@ public final class RelyingPartyResolveEntityContext extends BaseContext {
*
* @return the validated request
*/
- @Nullable public ResolveEntityRequest getValidatedRequest() {
+ @Nullable public Request getValidatedRequest() {
return validatedRequest;
}
@@ -51,8 +50,7 @@ public final class RelyingPartyResolveEntityContext extends BaseContext {
* @param request the validated request
* @return this context
*/
- @Nonnull public RelyingPartyResolveEntityContext setValidatedRequest(
- @Nullable final ResolveEntityRequest request) {
+ @Nonnull public RelyingPartyCachedMessageContext setValidatedRequest(@Nullable final Request request) {
validatedRequest = request;
return this;
}
@@ -72,7 +70,7 @@ public final class RelyingPartyResolveEntityContext extends BaseContext {
* @param response cached response
* @return this context
*/
- @Nonnull public RelyingPartyResolveEntityContext setCachedResponse(@Nullable final Response response) {
+ @Nonnull public RelyingPartyCachedMessageContext setCachedResponse(@Nullable final Response response) {
cachedResponse = response;
return this;
}
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateResolveEntityRequest.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateResolveEntityRequest.java
index 846aac2a..49cc1a1a 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateResolveEntityRequest.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateResolveEntityRequest.java
@@ -29,6 +29,8 @@ import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
import org.slf4j.Logger;
+import com.nimbusds.oauth2.sdk.Request;
+
import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.ResolveEntityRequest;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.LocalKeyContainer;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.SubjectEntityIDCriterion;
@@ -45,7 +47,7 @@ import net.shibboleth.shared.resolver.CriteriaSet;
/**
* Validates the resolve entity request against the profile configuration and stores the validated (possibly modified)
- * request into {@link RelyingPartyResolveEntityContext#setValidatedRequest(ResolveEntityRequest)}.
+ * request into {@link RelyingPartyCachedMessageContext#setValidatedRequest(Request)}.
*
* @event {@link EventIds#PROCEED_EVENT_ID}
* @event {@link EventIds#INVALID_MSG_CTX}
@@ -57,9 +59,9 @@ public class ValidateResolveEntityRequest extends AbstractProfileAction {
/** Class logger. */
@Nonnull private Logger log = LoggerFactory.getLogger(ValidateResolveEntityRequest.class);
- /** Strategy used to create the resolve entity context. */
+ /** Strategy used to create the cached message context. */
@Nonnull
- private Function<ProfileRequestContext, RelyingPartyResolveEntityContext> resolveEntityContextCreationStrategy;
+ private Function<ProfileRequestContext, RelyingPartyCachedMessageContext> cachedMessageContextCreationStrategy;
/** Cache containing local copies of trusted trust anchor keys. */
@NonnullAfterInit private MetadataCache<Map<String, LocalKeyContainer>> localTrustAnchorsCache;
@@ -67,18 +69,18 @@ public class ValidateResolveEntityRequest extends AbstractProfileAction {
/** Request message to operate on. */
@NonnullBeforeExec private ResolveEntityRequest requestMessage;
- /** Trust chain context to operate on. */
- @NonnullBeforeExec private RelyingPartyResolveEntityContext resolveEntityContext;
+ /** Cached message context to operate on. */
+ @NonnullBeforeExec private RelyingPartyCachedMessageContext cachedMessageContext;
/**
* Constructor.
*/
public ValidateResolveEntityRequest() {
- final Function<ProfileRequestContext, RelyingPartyResolveEntityContext> reccs =
- new ChildContextLookup<>(RelyingPartyResolveEntityContext.class, true).compose(
+ final Function<ProfileRequestContext, RelyingPartyCachedMessageContext> reccs =
+ new ChildContextLookup<>(RelyingPartyCachedMessageContext.class, true).compose(
new InboundMessageContextLookup());
assert reccs != null;
- resolveEntityContextCreationStrategy = reccs;
+ cachedMessageContextCreationStrategy = reccs;
}
/**
@@ -87,9 +89,9 @@ public class ValidateResolveEntityRequest extends AbstractProfileAction {
* @param strategy creation strategy
*/
public void setResolveEntityContextCreationStrategy(
- @Nonnull final Function<ProfileRequestContext, RelyingPartyResolveEntityContext> strategy) {
+ @Nonnull final Function<ProfileRequestContext, RelyingPartyCachedMessageContext> strategy) {
checkSetterPreconditions();
- resolveEntityContextCreationStrategy = Constraint.isNotNull(strategy,
+ cachedMessageContextCreationStrategy = Constraint.isNotNull(strategy,
"RelyingPartyResolveEntityContext creation strategy cannot be null");
}
@@ -132,8 +134,8 @@ public class ValidateResolveEntityRequest extends AbstractProfileAction {
return false;
}
- resolveEntityContext = resolveEntityContextCreationStrategy.apply(profileRequestContext);
- if (resolveEntityContext == null) {
+ cachedMessageContext = cachedMessageContextCreationStrategy.apply(profileRequestContext);
+ if (cachedMessageContext == null) {
log.error("{} Unable to create resolve entity context", getLogPrefix());
ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
return false;
@@ -153,7 +155,7 @@ public class ValidateResolveEntityRequest extends AbstractProfileAction {
return;
}
log.debug("{} The following trust anchors were validated: {}", getLogPrefix(), validatedAnchors);
- resolveEntityContext.setValidatedRequest(
+ cachedMessageContext.setValidatedRequest(
new ResolveEntityRequest(requestMessage.getEndpointURI(), requestMessage.getSubject(),
validatedAnchors, requestMessage.getEntityTypes()));
}
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateSelectedTrustChain.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateSelectedTrustChain.java
index 082cf41c..bd5038ff 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateSelectedTrustChain.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateSelectedTrustChain.java
@@ -72,7 +72,7 @@ public class ValidateSelectedTrustChain extends AbstractProfileAction {
/** Strategy used to locate the resolve entity context. */
@Nonnull
- private Function<ProfileRequestContext, RelyingPartyResolveEntityContext> resolveEntityContextLookupStrategy;
+ private Function<ProfileRequestContext, RelyingPartyCachedMessageContext> resolveEntityContextLookupStrategy;
/** The validated request to operate on. */
@NonnullBeforeExec private ResolveEntityRequest validatedRequest;
@@ -86,8 +86,8 @@ public class ValidateSelectedTrustChain extends AbstractProfileAction {
new InboundMessageContextLookup());
assert tcls != null;
trustChainContextLookupStrategy = tcls;
- final Function<ProfileRequestContext, RelyingPartyResolveEntityContext> recls =
- new ChildContextLookup<>(RelyingPartyResolveEntityContext.class).compose(
+ final Function<ProfileRequestContext, RelyingPartyCachedMessageContext> recls =
+ new ChildContextLookup<>(RelyingPartyCachedMessageContext.class).compose(
new InboundMessageContextLookup());
assert recls != null;
resolveEntityContextLookupStrategy = recls;
@@ -121,7 +121,7 @@ public class ValidateSelectedTrustChain extends AbstractProfileAction {
* @param strategy What to set.
*/
public void setResolveEntityContextLookupStrategy(
- @Nonnull final Function<ProfileRequestContext,RelyingPartyResolveEntityContext> strategy) {
+ @Nonnull final Function<ProfileRequestContext,RelyingPartyCachedMessageContext> strategy) {
checkSetterPreconditions();
resolveEntityContextLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null!");
}
@@ -143,14 +143,21 @@ public class ValidateSelectedTrustChain extends AbstractProfileAction {
return false;
}
- final RelyingPartyResolveEntityContext resolveEntityContext =
+ final RelyingPartyCachedMessageContext cachedResponseContext =
resolveEntityContextLookupStrategy.apply(profileRequestContext);
- if (resolveEntityContext == null || resolveEntityContext.getValidatedRequest() == null) {
- log.error("{} Could not resolve validated request messaGE", getLogPrefix());
+ if (cachedResponseContext == null) {
+ log.error("{} Could not resolve cached message context", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
+ return false;
+ }
+
+ if (cachedResponseContext.getValidatedRequest() instanceof ResolveEntityRequest resolveEntityRequest) {
+ validatedRequest = resolveEntityRequest;
+ } else {
+ log.error("{} Could not resolve request message", getLogPrefix());
ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
return false;
}
- validatedRequest = resolveEntityContext.getValidatedRequest();
return true;
}
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/navigate/CachedEntityStatementLifetimeLookupFunction.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/navigate/CachedEntityStatementLifetimeLookupFunction.java
deleted file mode 100644
index d8ca4f4f..00000000
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/navigate/CachedEntityStatementLifetimeLookupFunction.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.profile.navigate;
-
-import java.time.Duration;
-
-import javax.annotation.Nullable;
-
-import org.opensaml.profile.context.ProfileRequestContext;
-
-import net.shibboleth.profile.config.ProfileConfiguration;
-import net.shibboleth.profile.context.RelyingPartyContext;
-import net.shibboleth.profile.context.navigate.AbstractRelyingPartyLookupFunction;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.config.OIDFederationEntityConfigurationProfileConfiguration;
-
-/**
- * A function that returns
- * {@link OIDFederationEntityConfigurationProfileConfiguration#getCachedEntityStatementLifetime(ProfileRequestContext)} if such a profile
- * is available from a {@link RelyingPartyContext} obtained via a lookup function, by default a child of the
- * {@link ProfileRequestContext}.
- *
- * <p>If a specific setting is unavailable, a null value is returned.</p>
- */
-public class CachedEntityStatementLifetimeLookupFunction extends AbstractRelyingPartyLookupFunction<Duration> {
-
- /** {@inheritDoc} */
- @Override
- @Nullable public Duration apply(@Nullable final ProfileRequestContext input) {
- final RelyingPartyContext rpc = getRelyingPartyContextLookupStrategy().apply(input);
- if (rpc != null) {
- final ProfileConfiguration pc = rpc.getProfileConfig();
- if (pc instanceof OIDFederationEntityConfigurationProfileConfiguration ofec) {
- return ofec.getCachedEntityStatementLifetime(input);
- }
- }
-
- return null;
- }
-
-}
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/entity-configuration/entity-configuration-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/entity-configuration/entity-configuration-beans.xml
index b4db60a7..080dfc5a 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/entity-configuration/entity-configuration-beans.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/entity-configuration/entity-configuration-beans.xml
@@ -15,16 +15,38 @@
<util:constant id="shibboleth.metrics.ProfileCounter"
static-field="net.shibboleth.idp.plugin.oidc.op.oidfed.config.DefaultOIDFederationEntityConfigurationProfileConfiguration.PROFILE_COUNTER" />
- <bean id="BuildErrorResponseFromEvent"
- class="net.shibboleth.idp.plugin.oidc.op.profile.impl.BuildJSONErrorResponseFromEvent" scope="prototype"
- p:defaultStatusCode="500" p:defaultCode="server_error"
- p:httpServletResponseSupplier-ref="shibboleth.HttpServletResponseSupplier">
- <property name="eventContextLookupStrategy">
- <bean class="net.shibboleth.idp.profile.context.navigate.WebFlowCurrentEventLookupFunction" />
+ <bean id="shibboleth.oidfed.EntityConfigurationResponseMetadataCache" parent="shibboleth.oidc.CacheBuilder">
+ <constructor-arg>
+ <bean p:cacheId="DefaultEntityConfigurationResponseMetadataCache" parent="shibboleth.oidfed.EntityConfigurationResponseMetadataCacheBuilderSpec"
+ p:cleanupTaskInterval="PT30S"/>
+ </constructor-arg>
+ </bean>
+
+ <bean id="shibboleth.oidfed.EntityConfigurationResponseMetadataCacheBuilderSpec"
+ class="net.shibboleth.oidc.metadata.cache.impl.DynamicMetadataCacheBuilderSpec"
+ p:minCacheDuration="%{idp.oidfed.entity-configuration.maxRefreshDelay:PT1S}"
+ p:maxCacheDuration="%{idp.oidfed.entity-configuration.maxRefreshDelay:PT30S}">
+ <property name="criteriaToIdentifierStrategy">
+ <bean parent="shibboleth.Functions.Constant" c:target-ref="shibboleth.oidc.issuer" />
+ </property>
+ <property name="identifierExtractionStrategy">
+ <bean parent="shibboleth.Functions.Constant" c:target-ref="shibboleth.oidc.issuer" />
+ </property>
+ <property name="metadataExpirationTimeStrategy">
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.DefaultEntityConfigurationResponseContainerExpirationTimeStrategy"/>
+ </property>
+ <property name="metadataFilterStrategy">
+ <bean parent="shibboleth.BiFunctions.Expression" c:expression="#input1"/>
+ </property>
+ <property name="fetchStrategy">
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.DefaultEntityConfigurationResponseFetchingStrategy" />
</property>
</bean>
- <alias alias="ResponseCacheStorageService" name="%{idp.oidfed.entity.configurationCache:shibboleth.StorageService}" />
+ <bean id="LookupCachedEntityConfigurationResponse"
+ class="net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl.LookupCachedEntityConfigurationResponse"
+ scope="prototype"
+ p:responseCache-ref="shibboleth.oidfed.EntityConfigurationResponseMetadataCache" />
<bean id="InitializeEntityStatementContext"
class="net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl.InitializeEntityStatementContext"
@@ -92,7 +114,7 @@
</bean>
<bean id="FormOutboundMessage" class="net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl.FormOutboundFederationConfigurationResponse"
- scope="prototype" p:storageService-ref="ResponseCacheStorageService">
+ scope="prototype" p:responseCache-ref="shibboleth.oidfed.EntityConfigurationResponseMetadataCache">
</bean>
</beans>
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/entity-configuration/entity-configuration-flow.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/entity-configuration/entity-configuration-flow.xml
index f5036f68..670f03d7 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/entity-configuration/entity-configuration-flow.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/entity-configuration/entity-configuration-flow.xml
@@ -5,30 +5,15 @@
<action-state id="InitializeMandatoryContexts">
<on-entry>
- <set name="flowScope.transitionAfterInboundIntercept" value="'CheckIfValidCachedResponseExists'" />
+ <set name="flowScope.transitionAfterInboundIntercept" value="'LookupCachedResponse'" />
</on-entry>
</action-state>
- <decision-state id="CheckIfValidCachedResponseExists">
- <on-entry>
- <set name="requestScope.storageRecord"
- value="ResponseCacheStorageService.read(T(net.shibboleth.idp.plugin.oidc.op.oidfed.config.OIDFederationEntityConfigurationProfileConfiguration).PROFILE_ID, 'entityStatement')"/>
- <set name="requestScope.cachedEntityStatementJwt"
- value="storageRecord == null ? null : T(com.nimbusds.openid.connect.sdk.federation.entities.EntityStatement).parse(storageRecord.getValue())" />
- </on-entry>
- <if test="cachedEntityStatementJwt != null"
- then="UseCachedEntityStatement"
- else="InitializeEntityStatementContext" />
- </decision-state>
-
- <action-state id="UseCachedEntityStatement">
- <on-entry>
- <set name="requestScope.cachedResponseMessage"
- value="new com.nimbusds.openid.connect.sdk.federation.config.FederationEntityConfigurationSuccessResponse(cachedEntityStatementJwt)" />
- <evaluate expression="opensamlProfileRequestContext.ensureOutboundMessageContext().setMessage(cachedResponseMessage)"/>
- </on-entry>
- <evaluate expression="'proceed'"/>
- <transition on="proceed" to="PopulateOutboundInterceptContext"/>
+ <action-state id="LookupCachedResponse">
+ <evaluate expression="LookupCachedEntityConfigurationResponse" />
+ <evaluate expression="'proceed'" />
+ <transition on="CachedEntityConfigurationResponseFound" to="BuildResponseMessage" />
+ <transition on="proceed" to="InitializeEntityStatementContext" />
</action-state>
<action-state id="InitializeEntityStatementContext">
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/resolve-entity/resolve-entity-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/resolve-entity/resolve-entity-beans.xml
index e9bf3c4f..f4737f29 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/resolve-entity/resolve-entity-beans.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/resolve-entity/resolve-entity-beans.xml
@@ -68,8 +68,8 @@
scope="prototype"
p:localTrustAnchorsCache-ref="#{'%{idp.oidfed.resove-entity.LocalTrustAnchorsMetadataCache:shibboleth.oidfed.LocalTrustAnchorsMetadataCache}'.trim()}" />
- <bean id="LookupCachedResolveEntityRespomse"
- class="net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl.LookupCachedResolveEntityRespomse"
+ <bean id="LookupCachedResolveEntityResponse"
+ class="net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl.LookupCachedResolveEntityResponse"
scope="prototype"
p:responseCache-ref="shibboleth.oidfed.ResolveEntityResponseMetadataCache" />
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/resolve-entity/resolve-entity-flow.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/resolve-entity/resolve-entity-flow.xml
index 903e3fcc..f80f8802 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/resolve-entity/resolve-entity-flow.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/resolve-entity/resolve-entity-flow.xml
@@ -41,7 +41,7 @@
<action-state id="LookupCachedResponse">
<evaluate expression="ValidateRequest" />
- <evaluate expression="LookupCachedResolveEntityRespomse" />
+ <evaluate expression="LookupCachedResolveEntityResponse" />
<evaluate expression="'proceed'" />
<transition on="CachedResolveEntityResponseFound" to="BuildResponseMessage" />
<transition on="proceed" to="ResolveTrustChains" />
diff --git a/idp-oidc-extension-impl/src/test/resources/net/shibboleth/idp/module/conf/relying-party.xml b/idp-oidc-extension-impl/src/test/resources/net/shibboleth/idp/module/conf/relying-party.xml
index dc3a03ef..5b35615a 100644
--- a/idp-oidc-extension-impl/src/test/resources/net/shibboleth/idp/module/conf/relying-party.xml
+++ b/idp-oidc-extension-impl/src/test/resources/net/shibboleth/idp/module/conf/relying-party.xml
@@ -46,7 +46,7 @@
<bean parent="OAUTH2.Introspection" />
<bean parent="OAUTH2.Revocation" />
<bean parent="OAUTH2.PAR" />
- <bean parent="OIDFED.Configuration" p:cachedEntityStatementLifetime="PT2S" />
+ <bean parent="OIDFED.Configuration" p:cachedSuccessResponseLifetime="PT2S" />
<bean parent="OIDFED.ResolveEntity" />
</list>
</property>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list