[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