[java-idp-plugin-vci] 01/03: Profile rework

Codeberg noreply at shibboleth.net
Thu Dec 4 14:14:39 UTC 2025


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

codeberg pushed a commit to branch main
in repository java-idp-plugin-vci.

View the commit online:
https://codeberg.org/Shibboleth/java-idp-plugin-vci/commit/b2f37900a9eb66610eb428e04fccc52cf25ed32f

commit b2f37900a9eb66610eb428e04fccc52cf25ed32f
Author: jlauros <janne.lauros at csc.fi>
AuthorDate: Thu Dec 4 16:04:35 2025 +0200

    Profile rework
---
 .../impl/AbstractOpenIDVCIConfiguration.java       | 218 +------
 ...bstractOAuth2FlowAwareProfileConfiguration.java | 163 +++++
 .../impl/stolen/AbstractOIDCSSOConfiguration.java  | 705 +++++++++++++++++++++
 3 files changed, 871 insertions(+), 215 deletions(-)

diff --git a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/config/impl/AbstractOpenIDVCIConfiguration.java b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/config/impl/AbstractOpenIDVCIConfiguration.java
index 9869b43..798b78b 100644
--- a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/config/impl/AbstractOpenIDVCIConfiguration.java
+++ b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/config/impl/AbstractOpenIDVCIConfiguration.java
@@ -16,51 +16,23 @@
 
 package org.geant.shibboleth.plugin.openidvci.config.impl;
 
-import java.net.URI;
 import java.time.Duration;
-import java.util.Map;
-import java.util.function.BiFunction;
-import java.util.function.BiPredicate;
 import java.util.function.Function;
-import java.util.function.Predicate;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import org.geant.shibboleth.plugin.openidvci.config.OpenIDVCIConfiguration;
-import org.geant.shibboleth.plugin.openidvci.config.impl.stolen.AbstractOAuth2ClientAuthenticableProfileConfiguration;
+import org.geant.shibboleth.plugin.openidvci.config.impl.stolen.AbstractOIDCSSOConfiguration;
 import org.opensaml.profile.context.ProfileRequestContext;
 
-import net.shibboleth.oidc.profile.config.OIDCSSOProfileConfiguration;
-import net.shibboleth.profile.config.OverriddenIssuerProfileConfiguration;
 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;
-import net.shibboleth.shared.logic.PredicateSupport;
-import net.shibboleth.shared.primitive.StringSupport;
 
-public abstract class AbstractOpenIDVCIConfiguration extends AbstractOAuth2ClientAuthenticableProfileConfiguration
-        implements OpenIDVCIConfiguration, OverriddenIssuerProfileConfiguration, OIDCSSOProfileConfiguration {
-
-    /** Lookup function to override issuer value. */
-    @Nonnull
-    private Function<ProfileRequestContext, String> issuerLookupStrategy;
-
-    /** Lookup function to supply access token lifetime. */
-    @Nonnull
-    private Function<ProfileRequestContext, Duration> accessTokenLifetimeLookupStrategy;
-
-    /** Lookup function to supply access token type. */
-    @Nonnull
-    private Function<ProfileRequestContext, String> accessTokenTypeLookupStrategy;
-
-    /**
-     * Lookup function to supply strategy bi-function for manipulating access token
-     * claims set.
-     */
-    @Nonnull
-    private Function<ProfileRequestContext, BiFunction<ProfileRequestContext, Map<String, Object>, Map<String, Object>>> accessTokenClaimsSetManipulationStrategyLookupStrategy;
+public abstract class AbstractOpenIDVCIConfiguration extends AbstractOIDCSSOConfiguration
+        implements OpenIDVCIConfiguration {
 
     /** Lookup function to supply pre-authorized code lifetime. */
     @Nonnull
@@ -70,93 +42,13 @@ public abstract class AbstractOpenIDVCIConfiguration extends AbstractOAuth2Clien
     @Nonnull
     private Function<ProfileRequestContext, Integer> preauthorizedCodeLengthLookupStrategy;
 
-    /** Whether client is required to use PKCE. */
-    @Nonnull
-    private Predicate<ProfileRequestContext> forcePKCEPredicate;
-
-    /** Whether client is allowed to use PKCE code challenge method plain. */
-    @Nonnull
-    private Predicate<ProfileRequestContext> allowPKCEPlainPredicate;
-
     /**
      * Constructor.
      */
     protected AbstractOpenIDVCIConfiguration(@Nonnull @NotEmpty final String profileId) {
         super(profileId);
-        issuerLookupStrategy = FunctionSupport.constant(null);
-        accessTokenLifetimeLookupStrategy = FunctionSupport.constant(Duration.ofMinutes(10));
-        accessTokenTypeLookupStrategy = FunctionSupport.constant(null);
-        accessTokenClaimsSetManipulationStrategyLookupStrategy = FunctionSupport.constant(null);
         preauthorizedCodeLifetimeLookupStrategy = FunctionSupport.constant(Duration.ofMinutes(10));
         preauthorizedCodeLengthLookupStrategy = FunctionSupport.constant(Integer.valueOf(0));
-        forcePKCEPredicate = PredicateSupport.alwaysFalse();
-        allowPKCEPlainPredicate = PredicateSupport.alwaysFalse();
-    }
-
-    /**
-     * Set the lifetime of an access token.
-     * 
-     * @param lifetime lifetime of an access token
-     */
-    public void setAccessTokenLifetime(@Positive @Nonnull final Duration lifetime) {
-        Constraint.isTrue(lifetime != null && !lifetime.isZero() && !lifetime.isNegative(),
-                "Access token lifetime must be greater than 0");
-
-        accessTokenLifetimeLookupStrategy = FunctionSupport.constant(lifetime);
-    }
-
-    /**
-     * Set a lookup strategy for the access token lifetime.
-     *
-     * @param strategy lookup strategy
-     */
-    public void setAccessTokenLifetimeLookupStrategy(
-            @Nullable final Function<ProfileRequestContext, Duration> strategy) {
-        accessTokenLifetimeLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
-    }
-
-    /**
-     * Set access token type.
-     * 
-     * @param type token type, or null for unspecified/opaque
-     * 
-     */
-    public void setAccessTokenType(@Nullable @NotEmpty final String type) {
-        accessTokenTypeLookupStrategy = FunctionSupport.constant(StringSupport.trimOrNull(type));
-    }
-
-    /**
-     * Set lookup strategy for access token type.
-     * 
-     * @param strategy lookup strategy
-     * 
-     */
-    public void setAccessTokenTypeLookupStrategy(@Nonnull final Function<ProfileRequestContext, String> strategy) {
-        accessTokenTypeLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
-    }
-
-    /**
-     * Set the bi-function for manipulating access token claims set.
-     * 
-     * @param strategy bi-function for manipulating access token claims set
-     * 
-     */
-    public void setAccessTokenClaimsSetManipulationStrategy(
-            @Nullable final BiFunction<ProfileRequestContext, Map<String, Object>, Map<String, Object>> strategy) {
-        accessTokenClaimsSetManipulationStrategyLookupStrategy = FunctionSupport.constant(strategy);
-    }
-
-    /**
-     * Set a lookup strategy for the bi-function for manipulating access token
-     * claims set.
-     *
-     * @param strategy lookup strategy
-     * 
-     */
-    public void setAccessTokenClaimsSetManipulationStrategyLookupStrategy(
-            @Nonnull final Function<ProfileRequestContext, BiFunction<ProfileRequestContext, Map<String, Object>, Map<String, Object>>> strategy) {
-        accessTokenClaimsSetManipulationStrategyLookupStrategy = Constraint.isNotNull(strategy,
-                "Lookup strategy cannot be null");
     }
 
     /** {@inheritDoc} */
@@ -208,108 +100,4 @@ public abstract class AbstractOpenIDVCIConfiguration extends AbstractOAuth2Clien
         preauthorizedCodeLengthLookupStrategy = FunctionSupport.constant(codeLength);
     }
 
-    /**
-     * Set a lookup strategy for the pre-authorized code length. Length of zero
-     * means there is no requirement and code does not require storage
-     * configuration.
-     *
-     * @param strategy lookup strategy
-     */
-    public void setPreauthorizedCodeLengthLookupStrategy(
-            @Nullable final Function<ProfileRequestContext, Integer> strategy) {
-        preauthorizedCodeLengthLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    @Nullable
-    @NotEmpty
-    public String getIssuer(@Nullable final ProfileRequestContext profileRequestContext) {
-        return issuerLookupStrategy.apply(profileRequestContext);
-    }
-
-    /**
-     * Set overridden issuer value.
-     * 
-     * @param issuer issuer value
-     */
-    public void setIssuer(@Nullable @NotEmpty final String issuer) {
-        issuerLookupStrategy = FunctionSupport.constant(issuer);
-    }
-
-    /**
-     * Sets lookup strategy for overridden issuer value.
-     * 
-     * @param strategy lookup strategy
-     */
-    public void setIssuerLookupStrategy(@Nonnull final Function<ProfileRequestContext, String> strategy) {
-        issuerLookupStrategy = Constraint.isNotNull(strategy, "Issuer lookup strategy cannot be null");
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public Duration getAccessTokenLifetime(ProfileRequestContext profileRequestContext) {
-        final Duration lifetime = accessTokenLifetimeLookupStrategy.apply(profileRequestContext);
-
-        Constraint.isTrue(lifetime != null && !lifetime.isZero() && !lifetime.isNegative(),
-                "Access token lifetime must be greater than 0");
-        return lifetime;
-    }
-
-    /**
-     * Set whether client is required to use PKCE.
-     * 
-     * @param flag flag to set
-     */
-    public void setForcePKCE(final boolean flag) {
-        forcePKCEPredicate = flag ? PredicateSupport.alwaysTrue() : PredicateSupport.alwaysFalse();
-    }
-
-    /**
-     * Set condition for whether client is required to use PKCE.
-     * 
-     * @param condition condition to set
-     */
-    public void setForcePKCEPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
-        forcePKCEPredicate = Constraint.isNotNull(condition, "Condition cannot be null");
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public boolean isAllowPKCEPlain(@Nullable final ProfileRequestContext profileRequestContext) {
-        return allowPKCEPlainPredicate.test(profileRequestContext);
-    }
-
-    /**
-     * Set whether client is allowed to use PKCE code challenge method plain.
-     * 
-     * @param flag flag to set
-     */
-    public void setAllowPKCEPlain(final boolean flag) {
-        allowPKCEPlainPredicate = flag ? PredicateSupport.alwaysTrue() : PredicateSupport.alwaysFalse();
-    }
-
-    /**
-     * Set condition for whether client is allowed to use PKCE code challenge method
-     * plain.
-     * 
-     * @param condition condition to set
-     */
-    public void setAllowPKCEPlainPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
-        allowPKCEPlainPredicate = Constraint.isNotNull(condition, "Condition cannot be null");
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public boolean isForcePKCE(ProfileRequestContext profileRequestContext) {
-        return forcePKCEPredicate.test(profileRequestContext);
-    }
-
-    @Override
-    public BiPredicate<URI, ProfileRequestContext> getCustomRedirectUriValidationStrategy(
-            ProfileRequestContext profileRequestContext) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
 }
diff --git a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/config/impl/stolen/AbstractOAuth2FlowAwareProfileConfiguration.java b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/config/impl/stolen/AbstractOAuth2FlowAwareProfileConfiguration.java
new file mode 100644
index 0000000..3e31f1b
--- /dev/null
+++ b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/config/impl/stolen/AbstractOAuth2FlowAwareProfileConfiguration.java
@@ -0,0 +1,163 @@
+/*
+ * 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 org.geant.shibboleth.plugin.openidvci.config.impl.stolen;
+
+import java.util.function.Predicate;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.shibboleth.oidc.profile.config.OIDCFlowAwareProfileConfiguration;
+import net.shibboleth.oidc.profile.oauth2.config.OAuth2FlowAwareProfileConfiguration;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.logic.PredicateSupport;
+
+/**
+ * Base class for OIDC protocol configuration, containing configuration bits shared by all flow aware OIDC protocol
+ * configurations.
+ */
+public abstract class AbstractOAuth2FlowAwareProfileConfiguration 
+        extends AbstractOAuth2ClientAuthenticableProfileConfiguration implements OIDCFlowAwareProfileConfiguration, 
+        OAuth2FlowAwareProfileConfiguration {
+
+    /** Predicate used to indicate whether authorization code flow is supported by this profile. Default true. */
+    @Nonnull private Predicate<ProfileRequestContext> authorizationCodeFlowPredicate;
+
+    /** Predicate used to indicate whether implicit flow is supported by this profile. Default true. */
+    @Nonnull private Predicate<ProfileRequestContext> implicitFlowPredicate;
+
+    /** Predicate used to indicate whether hybrid flow is supported by this profile. Default true. */
+    @Nonnull private Predicate<ProfileRequestContext> hybridFlowPredicate;
+
+    /** Predicate used to indicate whether refresh tokens are supported by this profile. Default true. */
+    @Nonnull private Predicate<ProfileRequestContext> refreshTokensPredicate;
+
+    /**
+     * Constructor.
+     *
+     * @param profileId Unique profile identifier.
+     */
+    protected AbstractOAuth2FlowAwareProfileConfiguration(@Nonnull @NotEmpty final String profileId) {
+        super(profileId);
+        authorizationCodeFlowPredicate = PredicateSupport.alwaysTrue();
+        implicitFlowPredicate = PredicateSupport.alwaysTrue();
+        hybridFlowPredicate = PredicateSupport.alwaysTrue();
+        refreshTokensPredicate = PredicateSupport.alwaysTrue();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isAuthorizationCodeFlowEnabled(@Nullable final ProfileRequestContext profileRequestContext) {
+        return authorizationCodeFlowPredicate.test(profileRequestContext);
+    }
+
+    /**
+     * Set whether authorization code flow is supported by this profile.
+     * 
+     * @param flag flag to set
+     */
+    public void setAuthorizationCodeFlowEnabled(final boolean flag) {
+        authorizationCodeFlowPredicate = flag ? PredicateSupport.alwaysTrue() : PredicateSupport.alwaysFalse();
+    }
+
+    /**
+     * Set condition used to indicate whether authorization code flow is supported by this profile.
+     * 
+     * @param condition condition to set
+     */
+    public void setAuthorizationCodeFlowEnabledPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
+        authorizationCodeFlowPredicate = Constraint.isNotNull(condition,
+                "Condition used to indicate whether authorization code flow is supported cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isHybridFlowEnabled(@Nullable final ProfileRequestContext profileRequestContext) {
+        return hybridFlowPredicate.test(profileRequestContext);
+    }
+    
+    /**
+     * Set whether implicit flow is supported by this profile.
+     * 
+     * @param flag flag to set
+     */
+    public void setHybridFlowEnabled(final boolean flag) {
+        hybridFlowPredicate = flag ? PredicateSupport.alwaysTrue() : PredicateSupport.alwaysFalse();
+    }
+
+    /**
+     * Set condition used to indicate whether implicit flow is supported by this profile.
+     * 
+     * @param condition condition to set
+     */
+    public void setHybridFlowEnabledPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
+        hybridFlowPredicate = Constraint.isNotNull(condition,
+                "Condition used to indicate whether implicit flow is supported cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isImplicitFlowEnabled(@Nullable final ProfileRequestContext profileRequestContext) {
+        return implicitFlowPredicate.test(profileRequestContext);
+    }
+    
+    /**
+     * Set whether hybrid flow is supported by this profile.
+     * 
+     * @param flag flag to set
+     */
+    public void setImplicitFlowEnabled(final boolean flag) {
+        implicitFlowPredicate = flag ? PredicateSupport.alwaysTrue() : PredicateSupport.alwaysFalse();
+    }
+
+    /**
+     * Set condition used to indicate whether hybrid flow is supported by this profile.
+     * 
+     * @param condition condition to set.
+     */
+    public void setImplicitFlowEnabledPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
+        implicitFlowPredicate = Constraint.isNotNull(condition,
+                "Condition used to indicate whether hybrid flow is supported cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isRefreshTokensEnabled(@Nullable final ProfileRequestContext profileRequestContext) {
+        return refreshTokensPredicate.test(profileRequestContext);
+    }
+
+    /**
+     * Set whether refresh tokens are supported by this profile.
+     * 
+     * @param flag flag to set
+     */
+    public void setRefreshTokensEnabled(final boolean flag) {
+        refreshTokensPredicate = flag ? PredicateSupport.alwaysTrue() : PredicateSupport.alwaysFalse();
+    }
+
+    /**
+     * Set condition used to indicate whether refresh tokens are supported by this profile.
+     * 
+     * @param condition condition to set
+     */
+    public void setRefreshTokensEnabledPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
+        refreshTokensPredicate = Constraint.isNotNull(condition,
+                "Condition used to indicate whether refresh tokens are supported cannot be null");
+    }
+
+}
\ No newline at end of file
diff --git a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/config/impl/stolen/AbstractOIDCSSOConfiguration.java b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/config/impl/stolen/AbstractOIDCSSOConfiguration.java
new file mode 100644
index 0000000..05a54ac
--- /dev/null
+++ b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/config/impl/stolen/AbstractOIDCSSOConfiguration.java
@@ -0,0 +1,705 @@
+/*
+ * 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 org.geant.shibboleth.plugin.openidvci.config.impl.stolen;
+
+import java.net.URI;
+import java.time.Duration;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.BiFunction;
+import java.util.function.BiPredicate;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.shibboleth.oidc.profile.config.OIDCSSOProviderConfiguration;
+import net.shibboleth.oidc.profile.config.OIDCSSORelyingPartyConfiguration;
+import net.shibboleth.shared.annotation.constraint.NonnullElements;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.annotation.constraint.NotLive;
+import net.shibboleth.shared.annotation.constraint.Positive;
+import net.shibboleth.shared.collection.CollectionSupport;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.logic.FunctionSupport;
+import net.shibboleth.shared.logic.PredicateSupport;
+import net.shibboleth.shared.primitive.StringSupport;
+
+/**
+ * Base class for profiles that support OIDC's concept of SSO, which spans multiple endpoints.
+ */
+public abstract class AbstractOIDCSSOConfiguration extends AbstractOAuth2FlowAwareProfileConfiguration
+        implements OIDCSSORelyingPartyConfiguration, OIDCSSOProviderConfiguration {
+
+    /** Lookup function to override issuer value. */
+    @Nonnull private Function<ProfileRequestContext,String> issuerLookupStrategy;
+
+    /** Whether attributes should be resolved in the course of the profile. */
+    @Nonnull private Predicate<ProfileRequestContext> resolveAttributesPredicate;
+
+    /** Whether encryption is optional in the face of no key, etc. */
+    @Nonnull private Predicate<ProfileRequestContext> encryptionOptionalPredicate;
+    
+    /** Whether client is required to use PKCE. */
+    @Nonnull private Predicate<ProfileRequestContext> forcePKCEPredicate;
+
+    /** Whether client is allowed to use PKCE code challenge method plain. */
+    @Nonnull private Predicate<ProfileRequestContext> allowPKCEPlainPredicate;
+    
+    /** Lookup function to supply ID token lifetime. */
+    @Nonnull private Function<ProfileRequestContext,Duration> idTokenLifetimeLookupStrategy;
+
+    /** Lookup function to supply access token type. */
+    @Nonnull private Function<ProfileRequestContext,String> accessTokenTypeLookupStrategy;
+
+    /** Lookup function to supply refresh token type. */
+    @Nonnull private Function<ProfileRequestContext,String> refreshTokenTypeLookupStrategy;
+
+    /** Lookup function to supply access token lifetime. */
+    @Nonnull private Function<ProfileRequestContext,Duration> accessTokenLifetimeLookupStrategy;
+    
+    /** Lookup function to supply refresh token timeout. */
+    @Nonnull private Function<ProfileRequestContext,Duration> refreshTokenTimeoutLookupStrategy;
+
+    /** Lookup function to supply refresh token chain lifetime. */
+    @Nonnull private Function<ProfileRequestContext,Duration> refreshTokenChainLifetimeLookupStrategy;
+
+    /** Lookup function to supply additional audiences for ID token. */
+    @Nonnull private Function<ProfileRequestContext,Set<String>> assertionAudiencesLookupStrategy;
+
+    /** Lookup function to supply attribute IDs to include in ID token regardless of response_type. */
+    @Nonnull private Function<ProfileRequestContext,Set<String>> alwaysIncludedAttributesLookupStrategy;
+
+    /** Lookup function to supply strategy bi-function for manipulating id_token claims. */ 
+    @Nonnull
+    private Function<ProfileRequestContext,BiFunction<ProfileRequestContext,Map<String,Object>,Map<String,Object>>>
+        idTokenManipulationStrategyLookupStrategy;
+
+    /** Lookup function to supply strategy bi-function for manipulating access token claims set. */ 
+    @Nonnull
+    private Function<ProfileRequestContext,BiFunction<ProfileRequestContext,Map<String,Object>,Map<String,Object>>>
+        accessTokenClaimsSetManipulationStrategyLookupStrategy;    
+
+    /** Lookup function to supply strategy bi-predicate for custom valdation of redirect URI in the request. */
+    @Nonnull
+    private Function<ProfileRequestContext,BiPredicate<URI,ProfileRequestContext>>
+        customRedirectUriValidationStrategyLookupStrategy;
+
+    /** Whether the access token to be issued is always a bearer access token. */
+    @Nonnull private Predicate<ProfileRequestContext> alwaysIssueBearerAccessTokenPredicate;
+
+    /** Whether scope validation is strict, i.e. request for unallowed scopes is an error. */
+    @Nonnull private Predicate<ProfileRequestContext> strictScopeValidationPredicate;
+
+    /**
+     * Creates a new configuration instance.
+     *
+     * @param profileId Unique profile identifier.
+     */
+    public AbstractOIDCSSOConfiguration(@Nonnull @NotEmpty final String profileId) {
+        super(profileId);
+        issuerLookupStrategy = FunctionSupport.constant(null);
+        resolveAttributesPredicate = PredicateSupport.alwaysTrue();
+        encryptionOptionalPredicate = PredicateSupport.alwaysTrue();
+
+        forcePKCEPredicate = PredicateSupport.alwaysFalse();
+        allowPKCEPlainPredicate = PredicateSupport.alwaysFalse();
+        
+        idTokenLifetimeLookupStrategy = FunctionSupport.constant(Duration.ofHours(1));
+        accessTokenTypeLookupStrategy = FunctionSupport.constant(null);
+        accessTokenLifetimeLookupStrategy = FunctionSupport.constant(Duration.ofMinutes(10));
+        refreshTokenTimeoutLookupStrategy = FunctionSupport.constant(Duration.ofHours(2));
+        refreshTokenChainLifetimeLookupStrategy = FunctionSupport.constant(Duration.ofHours(2));
+        refreshTokenTypeLookupStrategy = FunctionSupport.constant(null);
+        
+        assertionAudiencesLookupStrategy = FunctionSupport.constant(null);
+        alwaysIncludedAttributesLookupStrategy = FunctionSupport.constant(null);
+
+        idTokenManipulationStrategyLookupStrategy = FunctionSupport.constant(null);
+        accessTokenClaimsSetManipulationStrategyLookupStrategy = FunctionSupport.constant(null);
+
+        customRedirectUriValidationStrategyLookupStrategy = FunctionSupport.constant(null);
+
+        alwaysIssueBearerAccessTokenPredicate = PredicateSupport.alwaysFalse();
+        strictScopeValidationPredicate = PredicateSupport.alwaysFalse();
+    }
+    
+    /** {@inheritDoc} */
+    @Override
+    @Nullable @NotEmpty public String getIssuer(@Nullable final ProfileRequestContext profileRequestContext) {
+        return issuerLookupStrategy.apply(profileRequestContext);
+    }
+    
+    /**
+     * Set overridden issuer value.
+     * 
+     * @param issuer issuer value
+     */
+    public void setIssuer(@Nullable @NotEmpty final String issuer) {
+        issuerLookupStrategy = FunctionSupport.constant(issuer);
+    }
+    
+    /**
+     * Sets lookup strategy for overridden issuer value.
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setIssuerLookupStrategy(@Nonnull final Function<ProfileRequestContext,String> strategy) {
+        issuerLookupStrategy = Constraint.isNotNull(strategy, "Issuer lookup strategy cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isResolveAttributes(@Nullable final ProfileRequestContext profileRequestContext) {
+        return resolveAttributesPredicate.test(profileRequestContext);
+    }
+
+    /**
+     * Set whether attributes should be resolved during the profile.
+     * 
+     * @param flag flag to set
+     */
+    public void setResolveAttributes(final boolean flag) {
+        resolveAttributesPredicate = flag ? PredicateSupport.alwaysTrue() : PredicateSupport.alwaysFalse();
+    }
+    
+    /**
+     * Set a condition to determine whether attributes should be resolved during the profile.
+     * 
+     * @param condition condition to set
+     */
+    public void setResolveAttributesPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
+        resolveAttributesPredicate = Constraint.isNotNull(condition, "Resolve attributes predicate cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isEncryptionOptional(@Nullable final ProfileRequestContext profileRequestContext) {
+        return encryptionOptionalPredicate.test(profileRequestContext);
+    }
+    
+    /**
+     * Set whether encryption is optional in the face of a missing key, etc.
+     * 
+     * @param flag  flag to set
+     */
+    public void setEncryptionOptional(final boolean flag) {
+        encryptionOptionalPredicate = flag ? PredicateSupport.alwaysTrue() : PredicateSupport.alwaysFalse();
+    }
+
+    /**
+     * Set a condition to determine whether encryption is optional in the face of a missing key, etc.
+     *
+     * @param condition condition to set
+     */
+    public void setEncryptionOptionalPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
+        encryptionOptionalPredicate = Constraint.isNotNull(condition, "Encryption optional predicate cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isForcePKCE(@Nullable final ProfileRequestContext profileRequestContext) {
+        return forcePKCEPredicate.test(profileRequestContext);
+    }
+
+   /**
+    * Set whether client is required to use PKCE.
+    * 
+    * @param flag flag to set
+    */
+    public void setForcePKCE(final boolean flag) {
+        forcePKCEPredicate = flag ? PredicateSupport.alwaysTrue() : PredicateSupport.alwaysFalse();
+    }
+
+   /**
+    * Set condition for whether client is required to use PKCE.
+    * 
+    * @param condition condition to set
+    */
+    public void setForcePKCEPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
+        forcePKCEPredicate = Constraint.isNotNull(condition, "Condition cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isAllowPKCEPlain(@Nullable final ProfileRequestContext profileRequestContext) {
+        return allowPKCEPlainPredicate.test(profileRequestContext);
+    }
+
+   /**
+    * Set whether client is allowed to use PKCE code challenge method plain.
+    * 
+    * @param flag flag to set
+    */
+    public void setAllowPKCEPlain(final boolean flag) {
+        allowPKCEPlainPredicate = flag ? PredicateSupport.alwaysTrue() : PredicateSupport.alwaysFalse();
+    }
+
+   /**
+    * Set condition for whether client is allowed to use PKCE code challenge method plain.
+    * 
+    * @param condition condition to set
+    */
+    public void setAllowPKCEPlainPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
+        allowPKCEPlainPredicate = Constraint.isNotNull(condition, "Condition cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    @Positive @Nonnull public Duration getIDTokenLifetime(@Nullable final ProfileRequestContext profileRequestContext) {
+        
+        final Duration lifetime = idTokenLifetimeLookupStrategy.apply(profileRequestContext);
+        
+        Constraint.isTrue(lifetime != null && !lifetime.isZero() && !lifetime.isNegative(),
+                "ID token lifetime must be greater than 0");
+        assert lifetime != null;
+        return lifetime;
+    }
+
+    /**
+     * Set the lifetime of an id token.
+     * 
+     * @param lifetime lifetime of an id token in milliseconds
+     */
+    public void setIDTokenLifetime(@Positive @Nonnull final Duration lifetime) {
+        final Duration idTokenLifetime = Constraint.isNotNull(lifetime, "ID token lifetime cannot be null");
+        Constraint.isTrue(!idTokenLifetime.isZero() && !idTokenLifetime.isNegative(),
+                "ID token lifetime must be greater than 0");
+        
+        idTokenLifetimeLookupStrategy = FunctionSupport.constant(idTokenLifetime);
+    }
+
+    /**
+     * Set a lookup strategy for the ID token lifetime.
+     *
+     * @param strategy lookup strategy
+     */
+    public void setIDTokenLifetimeLookupStrategy(@Nonnull final Function<ProfileRequestContext,Duration> strategy) {
+        idTokenLifetimeLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    @Nullable @NotEmpty public String getAccessTokenType(@Nullable final ProfileRequestContext profileRequestContext) {
+         return accessTokenTypeLookupStrategy.apply(profileRequestContext);
+     }
+    
+    /**
+     * Set access token type.
+     * 
+     * @param type token type, or null for unspecified/opaque
+     * 
+     * @since 2.1.0
+     */
+     public void setAccessTokenType(@Nullable @NotEmpty final String type) {
+         accessTokenTypeLookupStrategy = FunctionSupport.constant(StringSupport.trimOrNull(type));
+     }
+    
+    /**
+     * Set lookup strategy for access token type.
+     * 
+     * @param strategy lookup strategy
+     * 
+     * @since 2.1.0
+     */
+     public void setAccessTokenTypeLookupStrategy(@Nonnull final Function<ProfileRequestContext,String> strategy) {
+         accessTokenTypeLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
+     }
+
+     /** {@inheritDoc} */
+    @Override
+    @Positive @Nonnull
+    public Duration getAccessTokenLifetime(@Nullable final ProfileRequestContext profileRequestContext) {
+        final Duration lifetime = accessTokenLifetimeLookupStrategy.apply(profileRequestContext);
+        
+        Constraint.isTrue(lifetime != null && !lifetime.isZero() && !lifetime.isNegative(),
+                "Access token lifetime must be greater than 0");
+        assert lifetime != null;
+        return lifetime;
+    }
+    
+    /**
+     * Set the lifetime of an access token.
+     * 
+     * @param lifetime lifetime of an access token in milliseconds
+     */
+    public void setAccessTokenLifetime(@Positive @Nonnull final Duration lifetime) {
+        final Duration tokenLifetime = Constraint.isNotNull(lifetime, "Access token lifetime cannot be null");
+        Constraint.isTrue(!tokenLifetime.isZero() && !tokenLifetime.isNegative(),
+                "Access token lifetime must be greater than 0");
+        
+        accessTokenLifetimeLookupStrategy = FunctionSupport.constant(tokenLifetime);
+    }
+    
+    /**
+     * Set a lookup strategy for the access token lifetime.
+     *
+     * @param strategy lookup strategy
+     */
+    public void setAccessTokenLifetimeLookupStrategy(
+            @Nullable final Function<ProfileRequestContext,Duration> strategy) {
+        accessTokenLifetimeLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
+    }
+    
+    /** {@inheritDoc} */
+    @Override
+    @Nonnull @Positive
+    public Duration getRefreshTokenTimeout(@Nullable final ProfileRequestContext profileRequestContext) {
+        final Duration timeout = refreshTokenTimeoutLookupStrategy.apply(profileRequestContext);
+        
+        Constraint.isTrue(timeout != null && !timeout.isZero() && !timeout.isNegative(),
+                "Refresh token timeout must be greater than 0");
+        assert timeout != null;
+        return timeout;
+    }
+
+    /**
+     * Set the timeout of refresh token.
+     * 
+     * @param timeout timeout of an refresh token
+     * 
+     * @since 2.2.0
+     */
+    public void setRefreshTokenTimeout(@Nonnull @Positive final Duration timeout) {
+        final Duration tokenTimeout = Constraint.isNotNull(timeout, "Refresh token timeout cannot be null");
+        Constraint.isTrue(!tokenTimeout.isZero() && !timeout.isNegative(),
+                "Refresh token timeout must be greater than 0");
+        
+        refreshTokenTimeoutLookupStrategy = FunctionSupport.constant(tokenTimeout);
+    }
+
+    /**
+     * Set a lookup strategy for the refresh token timeout.
+     *
+     * @param strategy lookup strategy
+     * 
+     * @since 2.2.0
+     */
+    public void setRefreshTokenTimeoutLookupStrategy(
+            @Nullable final Function<ProfileRequestContext,Duration> strategy) {
+        refreshTokenTimeoutLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    @Nonnull @Positive
+    public Duration getRefreshTokenChainLifetime(@Nullable final ProfileRequestContext profileRequestContext) {
+        final Duration lifetime = refreshTokenChainLifetimeLookupStrategy.apply(profileRequestContext);
+        
+        Constraint.isTrue(lifetime != null && !lifetime.isZero() && !lifetime.isNegative(),
+                "Refresh token chain lifetime must be greater than 0");
+        assert lifetime != null;
+        return lifetime;
+    }
+
+    /**
+     * Set the lifetime of refresh token chain.
+     * 
+     * @param lifetime lifetime of a refresh token chain
+     * 
+     * @since 2.2.0
+     */
+    public void setRefreshTokenChainLifetime(@Nonnull @Positive final Duration lifetime) {
+        final Duration chainLifetime = Constraint.isNotNull(lifetime, "Refresh token chain lifetime cannot be null");
+        Constraint.isTrue(!chainLifetime.isZero() && !chainLifetime.isNegative(),
+                "Refresh token chain lifetime must be greater than 0");
+        
+        refreshTokenChainLifetimeLookupStrategy = FunctionSupport.constant(chainLifetime);
+    }
+
+    /**
+     * Set a lookup strategy for the refresh token chain lifetime.
+     *
+     * @param strategy lookup strategy
+     * 
+     * @since 2.2.0
+     */
+    public void setRefreshTokenChainLifetimeLookupStrategy(
+            @Nullable final Function<ProfileRequestContext,Duration> strategy) {
+        refreshTokenChainLifetimeLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    @Nullable @NotEmpty public String getRefreshTokenType(@Nullable final ProfileRequestContext profileRequestContext) {
+         return refreshTokenTypeLookupStrategy.apply(profileRequestContext);
+     }
+
+    /**
+     * Set refresh token type.
+     * 
+     * @param type token type, or null for unspecified/opaque
+     * 
+     * @since 3.1.0
+     */
+     public void setRefreshTokenType(@Nullable @NotEmpty final String type) {
+         refreshTokenTypeLookupStrategy = FunctionSupport.constant(StringSupport.trimOrNull(type));
+     }
+    
+    /**
+     * Set lookup strategy for token token type.
+     * 
+     * @param strategy lookup strategy
+     * 
+     * @since 3.1.0
+     */
+     public void setRefreshTokenTypeLookupStrategy(@Nonnull final Function<ProfileRequestContext,String> strategy) {
+         refreshTokenTypeLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
+     }
+
+     /** {@inheritDoc} */
+    @Override
+    @Nonnull @NonnullElements @NotLive public Set<String> getAdditionalAudiencesForIdToken(
+            @Nullable final ProfileRequestContext profileRequestContext) {
+        
+        final Set<String> audiences = assertionAudiencesLookupStrategy.apply(profileRequestContext);
+        if (audiences != null) {
+            return CollectionSupport.copyToSet(audiences);
+        }
+        return CollectionSupport.emptySet();
+    }
+
+    /**
+     * Set the set of audiences, in addition to the relying party(ies) to which the IdP is issuing the ID Token, with
+     * which the token may be shared.
+     * 
+     * @param audiences the additional audiences
+     */
+    public void setAdditionalAudiencesForIdToken(@Nullable @NonnullElements final Collection<String> audiences) {
+
+        if (audiences == null || audiences.isEmpty()) {
+            assertionAudiencesLookupStrategy = FunctionSupport.constant(null);
+        } else {
+            assertionAudiencesLookupStrategy = FunctionSupport.constant(
+                    Set.copyOf(StringSupport.normalizeStringCollection(audiences)));
+        }
+    }
+
+    /**
+     * Set a lookup strategy for the set of audiences, in addition to the relying party(ies) to which the IdP
+     * is issuing the ID Token, with which the token may be shared.
+     *
+     * @param strategy  lookup strategy
+     */
+    public void setAdditionalAudiencesForIdTokenLookupStrategy(
+            @Nonnull final Function<ProfileRequestContext,Set<String>> strategy) {
+        assertionAudiencesLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    @Nonnull @NonnullElements @NotLive public Set<String> getAlwaysIncludedAttributes(
+            @Nullable final ProfileRequestContext profileRequestContext) {
+        
+        final Set<String> attributes = alwaysIncludedAttributesLookupStrategy.apply(profileRequestContext);
+        if (attributes != null) {
+            return CollectionSupport.copyToSet(attributes);
+        }
+        return CollectionSupport.emptySet();
+    }
+
+    /**
+     * Set the set of attribute IDs which should be included in the ID token regardless of response_type.
+     * 
+     * <p>Default behavior is to include claims only with the implicit id_token type only, while any use
+     * of a back-channel relies on the user_info endpoint to get the claims. This setting forces certain
+     * attributes to be added to the ID token regardless of flow.</p>
+     * 
+     * @param attributes the attribute IDs to include in all cases
+     */
+    public void setAlwaysIncludedAttributes(@Nullable @NonnullElements final Collection<String> attributes) {
+
+        if (attributes == null || attributes.isEmpty()) {
+            alwaysIncludedAttributesLookupStrategy = FunctionSupport.constant(null);
+        } else {
+            alwaysIncludedAttributesLookupStrategy = FunctionSupport.constant(
+                    Set.copyOf(StringSupport.normalizeStringCollection(attributes)));
+        }
+    }
+
+    /**
+     * Set a lookup strategy for the attribute IDs which should be included in the ID token regardless of
+     * response_type.
+     *
+     * @param strategy  lookup strategy
+     */
+    public void setAlwaysIncludedAttributesLookupStrategy(
+            @Nonnull final Function<ProfileRequestContext,Set<String>> strategy) {
+        alwaysIncludedAttributesLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    @Nullable
+    public BiFunction<ProfileRequestContext,Map<String,Object>,Map<String,Object>> getIDTokenManipulationStrategy(
+            @Nullable final ProfileRequestContext profileRequestContext) {
+        return idTokenManipulationStrategyLookupStrategy.apply(profileRequestContext);
+    }
+
+    /**
+     * Set the bi-function for manipulating id_token claims.
+     * 
+     * @param strategy bi-function for manipulating id_token claims
+     * 
+     * @since 2.1.0
+     */
+    public void setIDTokenManipulationStrategy(
+            @Nullable final BiFunction<ProfileRequestContext,Map<String,Object>,Map<String,Object>> strategy) {
+        idTokenManipulationStrategyLookupStrategy = FunctionSupport.constant(strategy);
+    }
+
+    /**
+     * Set a lookup strategy for the bi-function for manipulating id_token claims.
+     *
+     * @param strategy lookup strategy
+     * 
+     * @since 2.1.0
+     */
+    public void setIDTokenManipulationStrategyLookupStrategy(@Nonnull final 
+            Function<ProfileRequestContext,BiFunction<ProfileRequestContext,Map<String,Object>,Map<String,Object>>>
+            strategy) {
+        idTokenManipulationStrategyLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    @Nullable
+    public BiFunction<ProfileRequestContext,Map<String,Object>,Map<String,Object>>
+        getAccessTokenClaimsSetManipulationStrategy(
+            @Nullable final ProfileRequestContext profileRequestContext) {
+        return accessTokenClaimsSetManipulationStrategyLookupStrategy.apply(profileRequestContext);
+    }
+
+    /**
+     * Set the bi-function for manipulating access token claims set.
+     * 
+     * @param strategy bi-function for manipulating access token claims set
+     * 
+     * @since 2.1.0
+     */
+    public void setAccessTokenClaimsSetManipulationStrategy(
+            @Nullable final BiFunction<ProfileRequestContext,Map<String,Object>,Map<String,Object>> strategy) {
+        accessTokenClaimsSetManipulationStrategyLookupStrategy = FunctionSupport.constant(strategy);
+    }
+
+    /**
+     * Set a lookup strategy for the bi-function for manipulating access token claims set.
+     *
+     * @param strategy lookup strategy
+     * 
+     * @since 2.1.0
+     */
+    public void setAccessTokenClaimsSetManipulationStrategyLookupStrategy(@Nonnull final 
+            Function<ProfileRequestContext,BiFunction<ProfileRequestContext,Map<String,Object>,Map<String,Object>>>
+            strategy) {
+        accessTokenClaimsSetManipulationStrategyLookupStrategy = Constraint.isNotNull(strategy,
+                "Lookup strategy cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    @Nullable public BiPredicate<URI,ProfileRequestContext> getCustomRedirectUriValidationStrategy(
+            @Nullable final ProfileRequestContext profileRequestContext) {
+        return customRedirectUriValidationStrategyLookupStrategy.apply(profileRequestContext);
+    }
+
+    /**
+     * Set the bi-predicate for custom validation of redirect URI in the request.
+     * .
+     * @param strategy bi-predicate for custom validation of redirect URI in the request
+     * 
+     * @since 3.2.0
+     */
+    public void setCustomRedirectUriValidationStrategy(
+            @Nullable final BiPredicate<URI,ProfileRequestContext> strategy) {
+        customRedirectUriValidationStrategyLookupStrategy = FunctionSupport.constant(strategy);
+    }
+
+    /**
+     * Set a lookup strategy for the bi-predicate for custom validation of redirect URI in the request.
+     * 
+     * @param strategy lookup strategy
+     * 
+     * @since 3.2.0
+     */
+    public void setCustomRedirectUriValidationStrategyLookupStrategy(@Nonnull final 
+            Function<ProfileRequestContext,BiPredicate<URI,ProfileRequestContext>> strategy) {
+        customRedirectUriValidationStrategyLookupStrategy = Constraint.isNotNull(strategy,
+                "Lookup strategy cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isAlwaysIssueBearerAccessToken(@Nullable final ProfileRequestContext profileRequestContext) {
+        return alwaysIssueBearerAccessTokenPredicate.test(profileRequestContext);
+    }
+
+    /**
+     * Set whether the access token to be issued is always a bearer access token.
+     * 
+     * @param flag flag to set
+     * 
+     * @since 3.2.0
+     */
+    public void setAlwaysIssueBearerAccessToken(final boolean flag) {
+        alwaysIssueBearerAccessTokenPredicate = flag ? PredicateSupport.alwaysTrue() : PredicateSupport.alwaysFalse();
+    }
+
+    /**
+     * Set a condition to determine whether the access token to be issued is always a bearer access token.
+     * 
+     * @param condition condition to set
+     * 
+     * @since 3.2.0
+     */
+    public void setAlwaysIssueBearerAccessTokenPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
+        alwaysIssueBearerAccessTokenPredicate = Constraint.isNotNull(condition,
+                "Always issue bearer access token predicate cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isStrictScopeValidation(@Nullable final ProfileRequestContext profileRequestContext) {
+        return strictScopeValidationPredicate.test(profileRequestContext);
+    }
+
+    /**
+     * Set whether scope validation is strict, i.e. request for unallowed scopes is an error.
+     * 
+     * @param flag flag to set
+     * 
+     * @since 3.2.0
+     */
+    public void setStrictScopeValidation(final boolean flag) {
+        strictScopeValidationPredicate = flag ? PredicateSupport.alwaysTrue() : PredicateSupport.alwaysFalse();
+    }
+
+    /**
+     * Set a condition to determine whether scope validation is strict, i.e. request for unallowed scopes is an error.
+     * 
+     * @param condition condition to set
+     * 
+     * @since 3.2.0
+     */
+    public void setStrictScopeValidationPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
+        strictScopeValidationPredicate = Constraint.isNotNull(condition,
+                "Strict scope validation predicate cannot be null");
+    }
+
+}

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


More information about the commits mailing list