[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