[java-plugin-shibd-oidc] branch main updated: WIP: Convert all request building handlers to strategies
Phil Smart
philip.smart at jisc.ac.uk
Tue Sep 30 13:04:28 UTC 2025
This is an automated email from the git hooks/post-receive script.
philsmart pushed a commit to branch main
in repository java-plugin-shibd-oidc.
View the commit online:
http://git.shibboleth.net/view/?p=java-plugin-shibd-oidc.git;a=commit;h=67496c2c79654ee0a7ba7f9b6c603f0e345971e9
The following commit(s) were added to refs/heads/main by this push:
new 67496c2 WIP: Convert all request building handlers to strategies
67496c2 is described below
commit 67496c2c79654ee0a7ba7f9b6c603f0e345971e9
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Tue Sep 30 14:04:24 2025 +0100
WIP: Convert all request building handlers to strategies
- Does not yet handle disallowed feature overrides, or fallback to the
profile configuration for those that are not specified in the DDF.
---
.../idp/flows/sp/initiator/oidc/oidc-beans.xml | 23 +-
.../sp/oidc/flows/OIDCAuthenticationFlowTest.java | 27 ++
...icationRequestParameterValueMessageHandler.java | 12 +-
...henticationRequestActionMessageHandlerNOPE.java | 277 ---------------------
...uthenticationContextClassRefLookupStrategy.java | 69 +++++
.../profile/impl/PKCEOptionsLookupStrategy.java | 57 +++++
.../impl/RequestedClaimsLookupStrategy.java | 56 +++++
...uthenticationContextClassReferencesHandler.java | 49 +---
...e.java => AddPKCECodeVerifierAndChallenge.java} | 19 +-
.../request/impl/AddRequestedClaimsHandler.java | 48 +---
.../profile/request/impl/AddScopesHandler.java | 1 +
.../sp/oidc/profile/request/impl/PKCEOptions.java | 9 +-
12 files changed, 274 insertions(+), 373 deletions(-)
diff --git a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/oidc/oidc-beans.xml b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/oidc/oidc-beans.xml
index 4470f79..e1d1855 100644
--- a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/oidc/oidc-beans.xml
+++ b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/oidc/oidc-beans.xml
@@ -140,18 +140,29 @@
</property>
</bean>
<bean id="AddRequestedClaims" scope="prototype"
- class="net.shibboleth.sp.oidc.profile.request.impl.AddRequestedClaimsHandler"
- p:requestedClaimsHook="#{getObject('shibboleth.authn.oidc.rp.RequestedClaimsHook')}" />
- <bean id="AddPCKECodeVerifierAndChallenge" scope="prototype"
- class="net.shibboleth.sp.oidc.profile.request.impl.AddPCKECodeVerifierAndChallenge"/>
+ class="net.shibboleth.sp.oidc.profile.request.impl.AddRequestedClaimsHandler">
+ <property name="parameterValueLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.impl.RequestedClaimsLookupStrategy" scope="prototype"/>
+ </property>
+ </bean>
+ <bean id="AddPKCECodeVerifierAndChallenge" scope="prototype"
+ class="net.shibboleth.sp.oidc.profile.request.impl.AddPKCECodeVerifierAndChallenge">
+ <property name="parameterValueLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.impl.PKCEOptionsLookupStrategy" scope="prototype"/>
+ </property>
+ </bean>
<bean id="AddRedirectURI" scope="prototype"
class="net.shibboleth.sp.oidc.profile.request.impl.AddRedirectURIHandler">
<property name="parameterValueLookupStrategy">
<bean class="net.shibboleth.sp.oidc.profile.impl.RedirectUriLookupStrategy" scope="prototype" />
</property>
- </bean>
+ </bean>
<bean id="AddAuthenticationContextClassReferences" scope="prototype"
- class="net.shibboleth.sp.oidc.profile.request.impl.AddAuthenticationContextClassReferencesHandler"/>
+ class="net.shibboleth.sp.oidc.profile.request.impl.AddAuthenticationContextClassReferencesHandler">
+ <property name="parameterValueLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.impl.AuthenticationContextClassRefLookupStrategy" scope="prototype" />
+ </property>
+ </bean>
<bean id="AddForceAuthentication" scope="prototype"
class="net.shibboleth.sp.oidc.profile.request.impl.AddForceAuthenticationHandler">
<property name="ParameterValueLookupStrategy">
diff --git a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCAuthenticationFlowTest.java b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCAuthenticationFlowTest.java
index 5b80749..59bdc14 100644
--- a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCAuthenticationFlowTest.java
+++ b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCAuthenticationFlowTest.java
@@ -168,6 +168,33 @@ public class OIDCAuthenticationFlowTest extends AbstractSPFlowTest {
final AuthorizationRequest req = validateOutputMessage(result);
}
+ /**
+ * Basic flow test with prompt=none.
+ *
+ * @throws IOException on error
+ * @throws MessageDecodingException
+ */
+ @Test
+ public void testACRFromAgent() throws IOException, MessageDecodingException {
+ setDefaultAuth();
+
+ final DDF input = new DDF(null).structure();
+ input.addmember(RemotedHttpServletRequest.STRUCTURE_NAME).structure();
+ input.addmember(InitiatorConstants.RESPONSE_URL).string(RESPONSE_URL);
+ input.addmember(SPConstants.TARGET).unsafe_string(RESOURCE_URL);
+ final DDF aclist = input.addmember(OIDCInitiatorConstants.AUTHN_CONTEXT_CLASS_REF).list();
+ aclist.add(new DDF(null).string("loa1"));
+ aclist.add(new DDF(null).string("loa2"));
+
+ setApplicationRequest("test-oidc-application", input);
+
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertFlowExecutionResult(result, FLOW_ID);
+ assertFlowExecutionOutcome(result.getOutcome());
+
+ final AuthorizationRequest req = validateOutputMessage(result);
+ }
+
/**
* Basic flow test with scope=email profile.
*
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractAuthenticationRequestParameterValueMessageHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractAuthenticationRequestParameterValueMessageHandler.java
index 3d9a4a7..347baa4 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractAuthenticationRequestParameterValueMessageHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractAuthenticationRequestParameterValueMessageHandler.java
@@ -23,6 +23,7 @@ import org.opensaml.messaging.context.MessageContext;
import org.opensaml.messaging.context.navigate.ChildContextLookup;
import org.opensaml.messaging.handler.AbstractMessageHandler;
import org.opensaml.messaging.handler.MessageHandlerException;
+import org.opensaml.profile.context.navigate.ParentProfileRequestContextLookup;
import org.slf4j.Logger;
import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
@@ -52,6 +53,10 @@ import net.shibboleth.shared.primitive.LoggerFactory;
* @param <T> the authentication request parameter value type
*/
public abstract class AbstractAuthenticationRequestParameterValueMessageHandler<T> extends AbstractMessageHandler {
+
+ /** Lookup function for parent ProfileRequestContext. */
+ @Nonnull protected static final ParentProfileRequestContextLookup<MessageContext> PRC_LOOKUP
+ = new ParentProfileRequestContextLookup<>();
/** Class logger. */
@Nonnull private final Logger log =
@@ -125,16 +130,15 @@ public abstract class AbstractAuthenticationRequestParameterValueMessageHandler<
*
* @param strategy The parameter value lookup strategy to set.
*/
- public void setParameterValueLookupStrategy(final Function<MessageContext, T> strategy) {
+ public void setParameterValueLookupStrategy(@Nonnull final Function<MessageContext, T> strategy) {
checkSetterPreconditions();
parameterValueLookupStrategy = Constraint.isNotNull(strategy,
"ParameterValueLookupStrategy can not be null");
}
/**
- * Retrieves the parameter value from the configured lookup strategy,
- * verifying at runtime that the result matches the type expected by
- * the subclass.
+ * Retrieves the parameter value or configuration options from the configured lookup strategy,
+ * verifying at runtime that the result matches the type expected by the subclass.
*
* @param context the message context to pass to the lookup function
*
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE.java
deleted file mode 100644
index de73cd8..0000000
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.shibboleth.sp.oidc.profile.impl;
-
-import java.util.function.Function;
-import java.util.function.Predicate;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.opensaml.messaging.context.MessageContext;
-import org.opensaml.messaging.context.navigate.ChildContextLookup;
-import org.opensaml.messaging.handler.MessageHandlerException;
-import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.profile.context.navigate.ParentProfileRequestContextLookup;
-import org.slf4j.Logger;
-
-import com.google.common.base.Predicates;
-import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
-
-import jakarta.servlet.http.HttpServletRequest;
-import net.shibboleth.oidc.metadata.context.OIDCProviderMetadataContext;
-import net.shibboleth.oidc.profile.config.OIDCAuthenticationRelyingPartyProfileConfiguration;
-import net.shibboleth.oidc.profile.core.OIDCAuthenticationRequest;
-import net.shibboleth.oidc.profile.messaging.context.OIDCPeerEntityContext;
-import net.shibboleth.profile.context.RelyingPartyContext;
-import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
-import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.primitive.LoggerFactory;
-import net.shibboleth.shared.primitive.NonnullSupplier;
-import net.shibboleth.sp.ddf.DDF;
-import net.shibboleth.sp.oidc.messaging.AbstractApplicationMessageHandler;
-
-/**
- * An abstract message handler that runs inside an {@link WebFlowMessageHandlerAdaptor}
- * that provides functions to make available various OIDC contexts.
- *
- * <p>The {@link MessageContext} will either be INBOUND or OUTBOUND depending on the direction defined
- * by the calling {@link WebFlowMessageHandlerAdaptor} action.</p>
- */
-public abstract class AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE extends AbstractApplicationMessageHandler {
-
- /** Lookup function for parent ProfileRequestContext. */
- @Nonnull private static final ParentProfileRequestContextLookup<MessageContext> PRC_LOOKUP
- = new ParentProfileRequestContextLookup<>();
-
- /** Class logger. */
- @Nonnull private final Logger log =
- LoggerFactory.getLogger(AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE.class);
-
- /** Lookup strategy to locate the OpenID Provider metadata to use.*/
- @Nonnull private Function<MessageContext, OIDCProviderMetadataContext> providerMetadataLookupStrategy;
-
- /** Lookup function for relying party context. */
- @Nonnull private Function<ProfileRequestContext,RelyingPartyContext> relyingPartyContextLookupStrategy;
-
- /** OIDC authentication request built by the IdP. */
- @NonnullBeforeExec private OIDCAuthenticationRequest authnRequest;
-
- /** OpenID Provider metadata .*/
- @NonnullBeforeExec private OIDCProviderMetadata providerMetadata;
-
- /** Applicable profile configuration. */
- @NonnullBeforeExec private OIDCAuthenticationRelyingPartyProfileConfiguration profileConfiguration;
-
- /** Current HTTP request, if available. */
- @Nullable private NonnullSupplier<HttpServletRequest> httpServletRequestSupplier;
-
- /** Input message from agent. */
- @NonnullBeforeExec private DDF input;
-
- /** Constructor.*/
- protected AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE() {
- providerMetadataLookupStrategy = new ChildContextLookup<>(OIDCProviderMetadataContext.class).compose(
- new ChildContextLookup<>(OIDCPeerEntityContext.class));
- relyingPartyContextLookupStrategy = new ChildContextLookup<>(RelyingPartyContext.class);
- }
-
- /**
- * Set the HTTP servlet request supplier.
- *
- * @param requestSupplier the supplier.
- */
- public void setHttpServletRequestSupplier(@Nullable final NonnullSupplier<HttpServletRequest> requestSupplier) {
- checkSetterPreconditions();
-
- httpServletRequestSupplier = requestSupplier;
- }
-
- /**
- * Get the HTTP servlet request supplier.
- *
- * @return the HTTP servlet request supplier
- */
- @Nullable public HttpServletRequest getHttpServletRequest() {
- if (httpServletRequestSupplier != null) {
- return httpServletRequestSupplier.get();
- }
- return null;
- }
-
- /**
- * Get the supplier for HTTP request if available.
- *
- * @return current HTTP request
- */
- @Nullable public NonnullSupplier<HttpServletRequest> getHttpServletRequestSupplier() {
- return httpServletRequestSupplier;
- }
-
- /**
- * Returns the authentication request build by this IdP. Should never be
- * {@code null} after after {@code doPreExecute} has been called.
- *
- * @return the authentication request.
- */
- @NonnullBeforeExec protected OIDCAuthenticationRequest getAuthenticationRequest() {
- return authnRequest;
- }
-
- /**
- * Returns the profile configuration associated with this request. Should never be
- * {@code null} after {@code doPreExecute} has been called.
- *
- * @return the profile configuration
- */
- @NonnullBeforeExec
- protected OIDCAuthenticationRelyingPartyProfileConfiguration getProfileConfiguration() {
- return profileConfiguration;
- }
-
-
- /**
- * Returns the OpenID Provider metadata. Should never be {@code null} after
- * after {@code doPreExecute} has been called.
- *
- * @return The provider metadata context.
- */
- @NonnullBeforeExec protected OIDCProviderMetadata getProviderMetadata() {
- return providerMetadata;
- }
-
- /**
- * Set the strategy used to locate the {@link RelyingPartyContext} associated with a given
- * {@link ProfileRequestContext}.
- *
- * @param strategy lookup strategy
- */
- public void setRelyingPartyContextLookupStrategy(
- @Nonnull final Function<ProfileRequestContext,RelyingPartyContext> strategy) {
- checkSetterPreconditions();
-
- relyingPartyContextLookupStrategy =
- Constraint.isNotNull(strategy, "RelyingPartyContext lookup strategy cannot be null");
- }
-
- /**
- * Set the lookup strategy to locate the OpenID providers metadata.
- *
- * @param strategy the strategy.
- */
- public void setProviderMetadataLookupStrategy(
- @Nonnull final Function<MessageContext, OIDCProviderMetadataContext> strategy) {
- checkSetterPreconditions();
-
- providerMetadataLookupStrategy =
- Constraint.isNotNull(strategy,"Provider metadata lookup strategy can not be null");
- }
-
-
- /**
- * Adapt a {@link ProfileRequestContext} function to a {@link MessageContext} function via composing
- * with a lookup function.
- *
- * @param function the profile request context function
- * @return the message context function
- *
- * @param <T> the output type of the functions
- */
- @Nullable protected <T> Function<MessageContext, T> adapt(
- @Nullable final Function<ProfileRequestContext, T> function) {
- if (function == null) {
- return null;
- }
- return function.compose(PRC_LOOKUP);
- }
-
- /**
- * Lookup the profile request context from the given message context using the function {@code PRC_LOOKUP}.
- *
- * @param messageContext the message context to find the profile request context from
- * @return the profile request context, or {@literal null} if not found
- */
- @Nullable protected ProfileRequestContext lookupProfileRequestContext(
- @Nonnull final MessageContext messageContext) {
- return PRC_LOOKUP.apply(messageContext);
- }
-
- /**
- * Adapt a {@link ProfileRequestContext} predicate into a {@link MessageContext} predicate via composing
- * with a lookup function.
- *
- * @param predicate the profile request context predicate
- * @return the message context predicate
- */
- @Nullable protected Predicate<MessageContext> adapt(@Nullable final Predicate<ProfileRequestContext> predicate) {
- if (predicate == null) {
- return null;
- }
- return Predicates.compose(predicate::test, PRC_LOOKUP::apply);
- }
-
-
- /**
- * Get the input message from the agent.
- *
- * @return input message
- */
- @NonnullBeforeExec public DDF getInput() {
- return input;
- }
-
-
- @Override
- protected boolean doPreInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
-
- if (!super.doPreInvoke(messageContext)) {
- return false;
- }
-
- if (!(messageContext.getMessage() instanceof OIDCAuthenticationRequest)) {
- throw new MessageHandlerException("Message was not an authentication request");
- }
- authnRequest = (OIDCAuthenticationRequest) messageContext.getMessage();
-
- final OIDCProviderMetadataContext providerMetadataContext =
- providerMetadataLookupStrategy.apply(messageContext);
- if (providerMetadataContext == null) {
- throw new MessageHandlerException("No provider metadata context found for peer");
- }
- providerMetadata = providerMetadataContext.getProviderInformation();
- if (providerMetadata == null) {
- throw new MessageHandlerException("No provider metadata context found for peer");
- }
- final var adaptedFunction = adapt(relyingPartyContextLookupStrategy);
- assert adaptedFunction != null;
- final RelyingPartyContext rpCtx = adaptedFunction.apply(messageContext);
- if (rpCtx != null && rpCtx.getConfiguration() != null &&
- rpCtx.getProfileConfig() instanceof final OIDCAuthenticationRelyingPartyProfileConfiguration rpConfig) {
- profileConfiguration = rpConfig;
- }
- if (profileConfiguration == null) {
- throw new MessageHandlerException("Profile configuration could not found");
- }
-
- input = ensureAgentRequestContext().getInput();
- if (input == null) {
- throw new MessageHandlerException("No input message");
- }
-
- return true;
- }
-
-
-}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AuthenticationContextClassRefLookupStrategy.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AuthenticationContextClassRefLookupStrategy.java
new file mode 100644
index 0000000..935b2e7
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AuthenticationContextClassRefLookupStrategy.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.sp.oidc.profile.impl;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.slf4j.Logger;
+
+import com.nimbusds.openid.connect.sdk.claims.ACR;
+
+import net.shibboleth.shared.collection.CollectionSupport;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.sp.ddf.DDF;
+import net.shibboleth.sp.oidc.profile.OIDCInitiatorConstants;
+
+
+/**
+ * A lookup strategy that extracts a list of {@link ACR} (Authentication Context Class References)
+ * from the input {@link DDF} message within the current {@link MessageContext}.
+ * <p>
+ * The extracted strings are converted into {@link ACR} objects and returned as an immutable list.
+ * If no input is available or the context is missing, the strategy returns {@code null}.
+ * </p>
+ */
+public class AuthenticationContextClassRefLookupStrategy
+ extends AbstractAgentAndRelyingPartyContextLookupFunction<List<ACR>> {
+
+ /** Logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AuthenticationContextClassRefLookupStrategy.class);
+
+ /** {@inheritDoc} */
+ @Nullable public List<ACR> apply(final MessageContext messageCtx) {
+ final DDF input = getDDF(messageCtx, DDFDirection.INPUT);
+ if (input == null) {
+ return null;
+ }
+ final List<String> classrefs = input.getmember(OIDCInitiatorConstants.AUTHN_CONTEXT_CLASS_REF).asList()
+ .stream()
+ .map(DDF::string)
+ .collect(CollectionSupport.nonnullCollector(Collectors.toUnmodifiableList())).get();
+
+
+// if (!classrefs.isEmpty() && profileConfiguration.isFeatureDisallowed(profileRequestContext,
+// BrowserSSOProfileConfiguration.FEATURE_AUTHNCONTEXT)) {
+// log.warn("{} Agent disallowed from overriding RequestedAuthnContext", getLogPrefix());
+// classrefs = CollectionSupport.emptyList();
+// }
+
+ return classrefs.stream().map(ACR::new).toList();
+
+ }
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/PKCEOptionsLookupStrategy.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/PKCEOptionsLookupStrategy.java
new file mode 100644
index 0000000..837b33d
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/PKCEOptionsLookupStrategy.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.sp.oidc.profile.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.profile.context.navigate.ParentProfileRequestContextLookup;
+
+import net.shibboleth.oidc.profile.config.OIDCAuthenticationRelyingPartyProfileConfiguration;
+import net.shibboleth.sp.oidc.profile.request.impl.PKCEOptions;
+
+
+/**
+ * A strategy function that looks up {@link PKCEOptions} from a {@link MessageContext}
+ * by consulting the {@link OIDCAuthenticationRelyingPartyProfileConfiguration} associated
+ * with the current request context. PKCE is checked to be enabled from the
+ * {@link OIDCAuthenticationRelyingPartyProfileConfiguration#isForceAuthn(ProfileRequestContext)}, and the method is
+ * taken from {@link OIDCAuthenticationRelyingPartyProfileConfiguration#isAllowPKCEPlain(ProfileRequestContext)}.
+ */
+public class PKCEOptionsLookupStrategy extends AbstractAgentAndRelyingPartyContextLookupFunction<PKCEOptions> {
+
+ /** Lookup function for parent ProfileRequestContext. */
+ @Nonnull private static final ParentProfileRequestContextLookup<MessageContext> PRC_LOOKUP
+ = new ParentProfileRequestContextLookup<>();
+
+ /** {@inheritDoc} */
+ @Override
+ public PKCEOptions apply(@Nullable final MessageContext messageContext) {
+
+ final OIDCAuthenticationRelyingPartyProfileConfiguration rpConfig =
+ getOIDCRelyingPartyProfileConfiguration(messageContext);
+ if (rpConfig == null) {
+ return null;
+ }
+ // If there is no other path, and the compiler can prove rpConfig is true, you can use it here.
+ final boolean enabled = rpConfig.isForcePKCE(PRC_LOOKUP.apply(messageContext));
+ final boolean allowPlain = rpConfig.isAllowPKCEPlain(PRC_LOOKUP.apply(messageContext));
+
+ return new PKCEOptions(enabled, allowPlain);
+ }
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/RequestedClaimsLookupStrategy.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/RequestedClaimsLookupStrategy.java
new file mode 100644
index 0000000..6a0718e
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/RequestedClaimsLookupStrategy.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.sp.oidc.profile.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.profile.context.navigate.ParentProfileRequestContextLookup;
+
+import com.nimbusds.openid.connect.sdk.OIDCClaimsRequest;
+
+import net.shibboleth.oidc.profile.config.OIDCAuthenticationRelyingPartyProfileConfiguration;
+import net.shibboleth.profile.context.RelyingPartyContext;
+
+
+/**
+ * A lookup strategy that resolves an {@link OIDCClaimsRequest} from the current {@link MessageContext}.
+ * <p>
+ * This strategy inspects the active {@link RelyingPartyContext} and its associated
+ * {@link OIDCAuthenticationRelyingPartyProfileConfiguration} to determine if a claims request
+ * is configured. If so, it returns the corresponding {@link OIDCClaimsRequest}; otherwise, it returns {@code null}.
+ * </p>
+ */
+public class RequestedClaimsLookupStrategy extends AbstractAgentAndRelyingPartyContextLookupFunction<OIDCClaimsRequest> {
+
+ /** Lookup function for parent ProfileRequestContext. */
+ @Nonnull private static final ParentProfileRequestContextLookup<MessageContext> PRC_LOOKUP
+ = new ParentProfileRequestContextLookup<>();
+
+ /** {@inheritDoc} */
+ @Override
+ public OIDCClaimsRequest apply(@Nullable final MessageContext messageContext) {
+
+ final OIDCAuthenticationRelyingPartyProfileConfiguration rpConfig =
+ getOIDCRelyingPartyProfileConfiguration(messageContext);
+ if (rpConfig == null) {
+ return null;
+ }
+ // TODO get this from the config?
+ return null;
+ }
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddAuthenticationContextClassReferencesHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddAuthenticationContextClassReferencesHandler.java
index f24a1e1..c01e8fc 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddAuthenticationContextClassReferencesHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddAuthenticationContextClassReferencesHandler.java
@@ -14,36 +14,40 @@
package net.shibboleth.sp.oidc.profile.request.impl;
-import java.security.Principal;
import java.util.List;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import org.opensaml.messaging.context.MessageContext;
import org.opensaml.messaging.handler.MessageHandlerException;
-import org.opensaml.profile.context.ProfileRequestContext;
import org.slf4j.Logger;
import com.nimbusds.openid.connect.sdk.claims.ACR;
-import net.shibboleth.oidc.profile.config.navigate.ProxyAwareDefaultOIDCAuthenticationContextClassRequestLookupFunction;
import net.shibboleth.shared.primitive.LoggerFactory;
-import net.shibboleth.sp.oidc.profile.impl.AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE;
+import net.shibboleth.sp.oidc.profile.impl.AbstractAuthenticationRequestParameterValueMessageHandler;
-/**
- * A message handler that adds any authentication context class references. TODO
+
+/**
+ * A message handler that adds Authentication Context Class References (ACRs) to an authentication request.
+ *
+ * <p>If no ACRs are present in the request, nothing it set onto the request</p>
*/
public class AddAuthenticationContextClassReferencesHandler
- extends AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE {
+ extends AbstractAuthenticationRequestParameterValueMessageHandler<List<ACR>> {
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(AddAuthenticationContextClassReferencesHandler.class);
+ /** Constructor.*/
+ public AddAuthenticationContextClassReferencesHandler() {
+ super((Class)List.class);
+ }
+
@Override protected void doInvoke(@Nonnull final MessageContext messageContext)
throws MessageHandlerException {
- final List<ACR> acrs = buildRequestedAuthnContext(lookupProfileRequestContext(messageContext));
+ final List<ACR> acrs = getParameterValue(messageContext);
if (acrs != null) {
log.trace("{} setting ACRs to '{}' ", getLogPrefix(), acrs);
getAuthenticationRequest().setAcrs(acrs);
@@ -51,31 +55,4 @@ public class AddAuthenticationContextClassReferencesHandler
log.trace("{} no ACRs requested", getLogPrefix());
}
}
-
- /**
- * Build a list of {@link ACR}s if warranted. Converted from any default authentication method {@link Principal}s.
- *
- * <p>By default for this proxy case, the authentication methods are mapped from the upstream request
- * by the default authentication methods e.g. using the
- * {@link ProxyAwareDefaultOIDCAuthenticationContextClassRequestLookupFunction}.</p>
- *
- * @param profileRequestContext current profile request context
- *
- * @return the list of ACRs.
- */
- @Nullable private List<ACR> buildRequestedAuthnContext(
- @Nullable final ProfileRequestContext profileRequestContext) {
-
- final List<Principal> principals = getProfileConfiguration()
- .getDefaultAuthenticationMethods(profileRequestContext);
- if (principals.isEmpty()) {
- return null;
- }
-
- return principals.stream()
- .map(p -> new ACR(p.getName())).toList();
- }
-
-
-
}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddPCKECodeVerifierAndChallenge.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddPKCECodeVerifierAndChallenge.java
similarity index 88%
rename from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddPCKECodeVerifierAndChallenge.java
rename to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddPKCECodeVerifierAndChallenge.java
index c4a2ea1..6b168b7 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddPCKECodeVerifierAndChallenge.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddPKCECodeVerifierAndChallenge.java
@@ -30,27 +30,34 @@ import net.shibboleth.shared.annotation.constraint.NotEmpty;
import net.shibboleth.shared.codec.Base64Support;
import net.shibboleth.shared.codec.EncodingException;
import net.shibboleth.shared.primitive.LoggerFactory;
-import net.shibboleth.sp.oidc.profile.impl.AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE;
+import net.shibboleth.sp.oidc.profile.impl.AbstractAuthenticationRequestParameterValueMessageHandler;
/**
* Create an OAuth 2.0 PCKE code_verifier to use in the token request, and derives a code_challenge for immediate use in
* the authorization request.
*/
-public class AddPCKECodeVerifierAndChallenge extends AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE {
+public class AddPKCECodeVerifierAndChallenge
+ extends AbstractAuthenticationRequestParameterValueMessageHandler<PKCEOptions> {
/** Logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(AddPCKECodeVerifierAndChallenge.class);
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddPKCECodeVerifierAndChallenge.class);
+
+ /** Constructor.*/
+ public AddPKCECodeVerifierAndChallenge() {
+ super(PKCEOptions.class);
+ }
@Override
protected void doInvoke(final MessageContext messageContext) throws MessageHandlerException {
- if (getProfileConfiguration().isForcePKCE(lookupProfileRequestContext(messageContext))) {
+ final PKCEOptions pkceOptions = getParameterValue(messageContext);
+
+ if (pkceOptions != null && pkceOptions.isEnabled()) {
log.trace("{} PKCE enabled, adding code_challenge to request", getLogPrefix());
final CodeChallengeMethod method =
- getProfileConfiguration().isAllowPKCEPlain(lookupProfileRequestContext(messageContext))
- ? CodeChallengeMethod.PLAIN : CodeChallengeMethod.S256;
+ pkceOptions.allowPlain() ? CodeChallengeMethod.PLAIN : CodeChallengeMethod.S256;
final String codeVerifier = generateCodeVerifier(32);
final String challenge = computeCodeChallenge(codeVerifier, method);
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddRequestedClaimsHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddRequestedClaimsHandler.java
index 312da18..e243088 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddRequestedClaimsHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddRequestedClaimsHandler.java
@@ -14,58 +14,36 @@
package net.shibboleth.sp.oidc.profile.request.impl;
-import java.util.function.Function;
-
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import org.opensaml.messaging.context.MessageContext;
import org.opensaml.messaging.handler.MessageHandlerException;
-import org.opensaml.profile.context.ProfileRequestContext;
import org.slf4j.Logger;
import com.nimbusds.openid.connect.sdk.OIDCClaimsRequest;
-import net.shibboleth.shared.logic.FunctionSupport;
import net.shibboleth.shared.primitive.LoggerFactory;
-import net.shibboleth.sp.oidc.profile.impl.AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE;
+import net.shibboleth.sp.oidc.profile.impl.AbstractAuthenticationRequestParameterValueMessageHandler;
/**
- * A message handler that adds requested claims to the under constructions authentication request.
- *
- * <p>The claims are added from a customizable strategy/hook. No additional claims are provided by default.</p>
+ * A message handler that adds requested claims to the authentication request.
*
- * <p>Also records in the request whether the upstream OP supports the claims parameter, for later inspection by
+ * <p>Also records in the request whether the OP supports the claims parameter, for later inspection by
* downstream components that only has access to the request e.g. an encoder.</p>
*/
-public class AddRequestedClaimsHandler extends AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE {
+public class AddRequestedClaimsHandler
+ extends AbstractAuthenticationRequestParameterValueMessageHandler<OIDCClaimsRequest> {
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(AddRequestedClaimsHandler.class);
- /** A hook that creates requested claims JSON Object from the profile request object.*/
- @Nonnull private Function<ProfileRequestContext, OIDCClaimsRequest> requestedClaimsHook;
-
/** Constructor.*/
public AddRequestedClaimsHandler() {
- requestedClaimsHook = FunctionSupport.constant(null);
+ super(OIDCClaimsRequest.class);
}
-
- /**
- * Set the hook that generates a requested claims JSON Object from the given profile request object.
- *
- * @param hook the hook
- */
- public void setRequestedClaimsHook(@Nullable final Function<ProfileRequestContext, OIDCClaimsRequest> hook) {
- checkSetterPreconditions();
- if (hook != null) {
- requestedClaimsHook = hook;
- }
- }
-
@Override protected void doInvoke(@Nonnull final MessageContext messageContext)
throws MessageHandlerException {
@@ -77,18 +55,12 @@ public class AddRequestedClaimsHandler extends AbstractOIDCAuthenticationRequest
return;
}
- final OIDCClaimsRequest requestedClaims =
- requestedClaimsHook.apply(lookupProfileRequestContext(messageContext));
+ final OIDCClaimsRequest requestedClaims = getParameterValue(messageContext);
if (requestedClaims != null) {
getAuthenticationRequest().setRequestedClaims(requestedClaims);
log.trace("{} Added requested claims '{}' to the authentication request",getLogPrefix(), requestedClaims);
} else {
log.trace("{} No individual claims requested", getLogPrefix());
- }
-
-
- }
-
-
-
-}
+ }
+ }
+}
\ No newline at end of file
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddScopesHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddScopesHandler.java
index 66d7fbd..a59bf40 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddScopesHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddScopesHandler.java
@@ -34,6 +34,7 @@ public class AddScopesHandler extends AbstractAuthenticationRequestParameterValu
/**
* Constructor.
*/
+ @SuppressWarnings({ "unchecked", "rawtypes" })
protected AddScopesHandler() {
super((Class)Set.class);
}
diff --git a/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/AuthenticationRequestParameterHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/PKCEOptions.java
similarity index 62%
rename from sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/AuthenticationRequestParameterHandler.java
rename to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/PKCEOptions.java
index fb196ef..4c638fb 100644
--- a/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/AuthenticationRequestParameterHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/PKCEOptions.java
@@ -12,14 +12,11 @@
* limitations under the License.
*/
-import java.util.function.Consumer;
-
-import org.opensaml.messaging.context.MessageContext;
+package net.shibboleth.sp.oidc.profile.request.impl;
/**
- * A marker interface for strategies that add OIDC authentication and OAuth authorization request parameters. Operates
- * directly on the message in the message context.
+ *
*/
-public interface AuthenticationRequestParameterHandler extends Consumer<MessageContext> {
+public record PKCEOptions(boolean isEnabled, boolean allowPlain) {
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list