[java-plugin-shibd-oidc] branch main updated: WIP: Refactor authorization request handlers into strategies
Phil Smart
philip.smart at jisc.ac.uk
Fri Sep 26 15:55:33 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=d6c07316ac76b69b6a78113f3734b24aa7df1843
The following commit(s) were added to refs/heads/main by this push:
new d6c0731 WIP: Refactor authorization request handlers into strategies
d6c0731 is described below
commit d6c07316ac76b69b6a78113f3734b24aa7df1843
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Fri Sep 26 16:55:31 2025 +0100
WIP: Refactor authorization request handlers into strategies
- Use strategies to locate the parameters to set
- Move Add handlers into a seperate temporary package. These will end
up in oidc-common
- Create strategies to locate the parameters in the correct place e.g.
DDF or profile. Noting, these are not complete and some will need
fallbacks and disallow lookups
---
.../AbstractApplicationMessageHandler.java | 2 +-
.../AuthenticationRequestParameterHandler.java | 11 +-
.../sp/oidc/profile/OIDCInitiatorConstants.java | 33 ++--
.../idp/flows/sp/initiator/oidc/oidc-beans.xml | 104 ++++++++---
.../sp/oidc/flows/OIDCAuthenticationFlowTest.java | 97 ++++++++++
...actOIDCAuthenticationRequestMessageHandler.java | 94 ----------
.../impl/AddForceAuthenticationHandler.java | 75 --------
.../sp/oidc/messaging/impl/AddNonceHandler.java | 74 --------
.../impl/AddPassiveAuthenticationHandler.java | 60 ------
.../oidc/messaging/impl/AddRedirectURIHandler.java | 82 ---------
.../impl/AddResponseTypeAndModeHandler.java | 204 ---------------------
...tAgentAndRelyingPartyContextLookupFunction.java | 128 +++++++++++++
...icationRequestParameterValueMessageHandler.java | 195 ++++++++++++++++++++
...enticationRequestActionMessageHandlerNOPE.java} | 8 +-
.../AbstractProviderMetadataLookupFunction.java | 71 +++++++
.../impl/AuthorizationEndpointLookupStrategy.java | 40 ++++
.../impl/BuildPlainRequestObjectJWT.java | 11 +-
.../impl/DisplayParameterLookupStrategy.java | 38 ++++
.../impl/ForceAuthnParameterLookupStrategy.java | 65 +++++++
.../impl/InitializeOAuth2ClientContext.java | 1 +
.../oidc/profile/impl/LoginHintLookupStrategy.java | 38 ++++
.../sp/oidc/profile/impl/MaxAgeLookupStrategy.java | 44 +++++
.../impl/NonceLookupStrategy.java} | 20 +-
.../sp/oidc/profile/impl/OIDCSupport.java | 6 +-
.../sp/oidc/profile/impl/PromptLookupStrategy.java | 54 ++++++
.../profile/impl/RedirectUriLookupStrategy.java | 53 ++++++
.../profile/impl/ResponseModeLookupStrategy.java | 96 ++++++++++
.../profile/impl/ResponseTypeLookupStrategy.java | 93 ++++++++++
.../sp/oidc/profile/impl/ScopeLookupStrategy.java | 49 +++++
.../impl/SetAuthenticationRequestTimeHandler.java | 11 +-
.../impl/StateLookupStrategy.java} | 19 +-
.../{messaging => profile}/impl/package-info.java | 4 +-
...uthenticationContextClassReferencesHandler.java | 8 +-
.../request}/impl/AddDisplayHandler.java | 22 ++-
.../request}/impl/AddEndpointURIHandler.java | 17 +-
.../impl/AddForceAuthenticationHandler.java | 69 +++++++
.../request}/impl/AddLoginHintHandler.java | 14 +-
.../request}/impl/AddMaxAgeHandler.java | 18 +-
.../request/impl/AddNonceHandler.java} | 37 ++--
.../impl/AddPCKECodeVerifierAndChallenge.java | 7 +-
.../profile/request/impl/AddPromptHandler.java | 54 ++++++
.../request/impl/AddRedirectURIHandler.java | 56 ++++++
.../request}/impl/AddRequestedClaimsHandler.java | 5 +-
.../request/impl/AddResponseModeHandler.java | 104 +++++++++++
.../request/impl/AddResponseTypeHandler.java | 114 ++++++++++++
.../request}/impl/AddScopesHandler.java | 17 +-
.../request}/impl/AddStateHandler.java | 45 ++---
.../request}/impl/package-info.java | 4 +-
48 files changed, 1725 insertions(+), 746 deletions(-)
diff --git a/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/messaging/AbstractApplicationMessageHandler.java b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/messaging/AbstractApplicationMessageHandler.java
index 2796923..f380043 100644
--- a/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/messaging/AbstractApplicationMessageHandler.java
+++ b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/messaging/AbstractApplicationMessageHandler.java
@@ -29,7 +29,7 @@ import net.shibboleth.sp.Application;
*/
public abstract class AbstractApplicationMessageHandler extends AbstractAgentMessageHandler {
- /** Cached agent from context. */
+ /** Cached Application from context. */
@NonnullBeforeExec private Application application;
/** {@inheritDoc} */
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/package-info.java b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/AuthenticationRequestParameterHandler.java
similarity index 61%
copy from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/package-info.java
copy to sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/AuthenticationRequestParameterHandler.java
index 91d9f47..fb196ef 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/package-info.java
+++ b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/AuthenticationRequestParameterHandler.java
@@ -12,7 +12,14 @@
* limitations under the License.
*/
+import java.util.function.Consumer;
+
+import org.opensaml.messaging.context.MessageContext;
+
/**
- * Package that contains message handlers.
+ * A marker interface for strategies that add OIDC authentication and OAuth authorization request parameters. Operates
+ * directly on the message in the message context.
*/
-package net.shibboleth.sp.oidc.messaging.impl;
\ No newline at end of file
+public interface AuthenticationRequestParameterHandler extends Consumer<MessageContext> {
+
+}
diff --git a/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/OIDCInitiatorConstants.java b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/OIDCInitiatorConstants.java
index 46ade91..107bd27 100644
--- a/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/OIDCInitiatorConstants.java
+++ b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/OIDCInitiatorConstants.java
@@ -17,39 +17,38 @@ package net.shibboleth.sp.oidc.profile;
import javax.annotation.Nonnull;
import org.opensaml.saml.saml2.core.AuthnContextClassRef;
-import org.opensaml.saml.saml2.core.NameIDPolicy;
-import org.opensaml.saml.saml2.metadata.NameIDFormat;
import net.shibboleth.shared.annotation.constraint.NotEmpty;
/**
* Constants for OIDC session initiator operations.
- *
- * TODO these are not all correct for OIDC
*/
public final class OIDCInitiatorConstants {
/** ForceAuthn input parameter. */
@Nonnull @NotEmpty public static final String FORCE_AUTHN = "forceAuthn";
-
+
+ /** Display input parameter. */
+ @Nonnull @NotEmpty public static final String DISPLAY = "display";
+
+ /** Login_hint input parameter. */
+ @Nonnull @NotEmpty public static final String LOGIN_HINT = "login_hint";
+
+ /** Login_hint input parameter. */
+ @Nonnull @NotEmpty public static final String MAX_AGE = "max_age";
+
/** IsPassive input parameter. */
@Nonnull @NotEmpty public static final String IS_PASSIVE = "isPassive";
+
+ /** Prompt parameter */
+ @Nonnull @NotEmpty public static final String PROMPT = "prompt";
+
+ /** Scope parameter */
+ @Nonnull @NotEmpty public static final String SCOPE = "scope";
/** authnContextClassRef input parameter. */
@Nonnull @NotEmpty public static final String AUTHN_CONTEXT_CLASS_REF = AuthnContextClassRef.DEFAULT_ELEMENT_LOCAL_NAME;
- /** authnContextComparison input parameter. */
- @Nonnull @NotEmpty public static final String AUTHN_CONTEXT_COMPARISON = "authnContextComparison";
-
- /** AttributeConsumingServiceIndex input parameter. */
- @Nonnull @NotEmpty public static final String ATTRIBUTE_INDEX = "attributeIndex";
-
- /** NameIDFormat input parameter. */
- @Nonnull @NotEmpty public static final String NAMEID_FORMAT = NameIDFormat.DEFAULT_ELEMENT_LOCAL_NAME;
-
- /** SPNameQualifier input parameter. */
- @Nonnull @NotEmpty public static final String SP_NAME_QUALIFIER = NameIDPolicy.SP_NAME_QUALIFIER_ATTRIB_NAME;
-
/** Private constructor. */
private OIDCInitiatorConstants() {
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 84b3c6d..4470f79 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
@@ -25,8 +25,10 @@
<bean id="WebFlowOutboundMessageHandlerAdaptor"
class="net.shibboleth.sp.profile.impl.WebFlowMessageHandlerAdaptor" scope="prototype" abstract="true"
c:executionDirection="OUTBOUND" />
+
+ <!-- TODO Check we need the thread-local variants of these in the chains we are using them ^^ -->
- <util:constant id="shiibboleth.sp.oidc.ProfileId"
+ <util:constant id="shibboleth.sp.oidc.ProfileId"
static-field="net.shibboleth.oidc.profile.config.OIDCSSOProfileConfiguration.PROFILE_ID" />
<!-- end -->
@@ -62,7 +64,7 @@
<bean id="SelectProfileConfiguration"
class="net.shibboleth.idp.profile.impl.SelectProfileConfiguration" scope="prototype"
- p:profileId-ref="shiibboleth.sp.oidc.ProfileId" />
+ p:profileId-ref="shibboleth.sp.oidc.ProfileId" />
<!-- <bean id="InitializeOutboundMessageContext"
class="net.shibboleth.idp.saml.profile.impl.InitializeOutboundMessageContext" scope="prototype"
@@ -87,40 +89,81 @@
<bean class="org.opensaml.messaging.handler.impl.BasicMessageHandlerChain">
<property name="handlers">
<list>
- <bean id="AddResponseTypeAndMode" scope="prototype"
- class="net.shibboleth.sp.oidc.messaging.impl.AddResponseTypeAndModeHandler"/>
+ <!-- Response_type must come before response_mode -->
+ <bean id="AddResponseType" scope="prototype"
+ class="net.shibboleth.sp.oidc.profile.request.impl.AddResponseTypeHandler">
+ <property name="parameterValueLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.impl.ResponseTypeLookupStrategy" scope="prototype"/>
+ </property>
+ </bean>
+ <bean id="AddResponseMode" scope="prototype"
+ class="net.shibboleth.sp.oidc.profile.request.impl.AddResponseModeHandler">
+ <property name="parameterValueLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.impl.ResponseModeLookupStrategy" scope="prototype"/>
+ </property>
+ </bean>
+
<bean id="AddMaxAge" scope="prototype"
- class="net.shibboleth.sp.oidc.messaging.impl.AddMaxAgeHandler"/>
+ class="net.shibboleth.sp.oidc.profile.request.impl.AddMaxAgeHandler">
+ <property name="parameterValueLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.impl.MaxAgeLookupStrategy" scope="prototype"/>
+ </property>
+ </bean>
<bean id="AddDisplay" scope="prototype"
- class="net.shibboleth.sp.oidc.messaging.impl.AddDisplayHandler"/>
+ class="net.shibboleth.sp.oidc.profile.request.impl.AddDisplayHandler" >
+ <property name="parameterValueLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.impl.DisplayParameterLookupStrategy" scope="prototype"/>
+ </property>
+ </bean>
<bean id="AddScopes" scope="prototype"
- class="net.shibboleth.sp.oidc.messaging.impl.AddScopesHandler"/>
+ class="net.shibboleth.sp.oidc.profile.request.impl.AddScopesHandler">
+ <property name="parameterValueLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.impl.ScopeLookupStrategy" scope="prototype"/>
+ </property>
+ </bean>
<bean id="AddNonce" scope="prototype"
- class="net.shibboleth.sp.oidc.messaging.impl.AddNonceHandler"/>
+ class="net.shibboleth.sp.oidc.profile.request.impl.AddNonceHandler">
+ <property name="parameterValueLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.impl.NonceLookupStrategy" scope="prototype"/>
+ </property>
+ </bean>
<bean id="AddEndpointURI" scope="prototype"
- class="net.shibboleth.sp.oidc.messaging.impl.AddEndpointURIHandler"/>
+ class="net.shibboleth.sp.oidc.profile.request.impl.AddEndpointURIHandler">
+ <property name="parameterValueLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.impl.AuthorizationEndpointLookupStrategy" scope="prototype"/>
+ </property>
+ </bean>
<bean id="AddLoginHintHandler" scope="prototype"
- class="net.shibboleth.sp.oidc.messaging.impl.AddLoginHintHandler"/>
+ class="net.shibboleth.sp.oidc.profile.request.impl.AddLoginHintHandler">
+ <property name="parameterValueLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.impl.LoginHintLookupStrategy" scope="prototype"/>
+ </property>
+ </bean>
<bean id="AddRequestedClaims" scope="prototype"
- class="net.shibboleth.sp.oidc.messaging.impl.AddRequestedClaimsHandler"
+ 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.messaging.impl.AddPCKECodeVerifierAndChallenge"/>
+ class="net.shibboleth.sp.oidc.profile.request.impl.AddPCKECodeVerifierAndChallenge"/>
<bean id="AddRedirectURI" scope="prototype"
- class="net.shibboleth.sp.oidc.messaging.impl.AddRedirectURIHandler"
- p:httpServletRequestSupplier-ref="shibboleth.RemotedHttpServletRequestSupplier"
- p:redirectUriCreationStrategy="#{getObject('shibboleth.authn.oidc.rp.RedirectUriCreationStrategy') ?:
- getObject('DefaultRedirectUriCreationStrategy')}" />
+ 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 id="AddAuthenticationContextClassReferences" scope="prototype"
- class="net.shibboleth.sp.oidc.messaging.impl.AddAuthenticationContextClassReferencesHandler"/>
+ class="net.shibboleth.sp.oidc.profile.request.impl.AddAuthenticationContextClassReferencesHandler"/>
<bean id="AddForceAuthentication" scope="prototype"
- class="net.shibboleth.sp.oidc.messaging.impl.AddForceAuthenticationHandler" />
- <!--
- Set passive authentication, prompt=none. Run after forced authentication (prompt=login) so this will take precedence
- but the max_age value will be left (if forced authentication is used).
- -->
- <bean id="AddPassiveAuthentication" scope="prototype"
- class="net.shibboleth.sp.oidc.messaging.impl.AddPassiveAuthenticationHandler" />
+ class="net.shibboleth.sp.oidc.profile.request.impl.AddForceAuthenticationHandler">
+ <property name="ParameterValueLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.impl.ForceAuthnParameterLookupStrategy"/>
+ </property>
+ </bean>
+ <bean id="AddPrompt" scope="prototype"
+ class="net.shibboleth.sp.oidc.profile.request.impl.AddPromptHandler">
+ <property name="parameterValueLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.impl.PromptLookupStrategy" scope="prototype"/>
+ </property>
+ </bean>
</list>
</property>
</bean>
@@ -231,12 +274,15 @@
scope="prototype">
<property name="handlers">
<list>
- <bean id="AddState" class="net.shibboleth.sp.oidc.messaging.impl.AddStateHandler"
- scope="prototype"
- p:stateGenerationStrategy="#{getObject('shibboleth.authn.oidc.rp.StateGenerationStrategy')}" />
+ <bean id="AddState" class="net.shibboleth.sp.oidc.profile.request.impl.AddStateHandler"
+ scope="prototype">
+ <property name="parameterValueLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.impl.StateLookupStrategy" scope="prototype"/>
+ </property>
+ </bean>
<bean id="BuildPlainRequestObjectJWT"
- class="net.shibboleth.sp.oidc.messaging.impl.BuildPlainRequestObjectJWT"
+ class="net.shibboleth.sp.oidc.profile.impl.BuildPlainRequestObjectJWT"
scope="prototype" />
<bean id="SignRequestObject" class="net.shibboleth.oidc.security.impl.SignJWTHandler"
@@ -264,7 +310,7 @@
</property>
</bean>
<bean id="SetAuthenticationRequestTime"
- class="net.shibboleth.sp.oidc.messaging.impl.SetAuthenticationRequestTimeHandler" scope="prototype"/>
+ class="net.shibboleth.sp.oidc.profile.impl.SetAuthenticationRequestTimeHandler" scope="prototype"/>
</list>
</property>
</bean>
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 6b13737..5b80749 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
@@ -120,6 +120,103 @@ public class OIDCAuthenticationFlowTest extends AbstractSPFlowTest {
final AuthorizationRequest req = validateOutputMessage(result);
}
+ /**
+ * Basic flow test with max_age.
+ *
+ * @throws IOException on error
+ * @throws MessageDecodingException
+ */
+ @Test
+ public void testMaxAgeFromAgent() 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);
+ input.addmember(OIDCInitiatorConstants.MAX_AGE).longinteger(60l);
+ 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 prompt=none.
+ *
+ * @throws IOException on error
+ * @throws MessageDecodingException
+ */
+ @Test
+ public void testPromptFromAgent() 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);
+ input.addmember(OIDCInitiatorConstants.PROMPT).string("none");
+ 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.
+ *
+ * @throws IOException on error
+ * @throws MessageDecodingException
+ */
+ @Test
+ public void testScopeFromAgent() 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);
+ input.addmember(OIDCInitiatorConstants.SCOPE).string("email profile");
+ setApplicationRequest("test-oidc-application", input);
+
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertFlowExecutionResult(result, FLOW_ID);
+ assertFlowExecutionOutcome(result.getOutcome());
+ //TODO TEST THE SCOPES
+ final AuthorizationRequest req = validateOutputMessage(result);
+ }
+
+
+ /**
+ * Basic flow test with display.
+ *
+ * @throws IOException on error
+ * @throws MessageDecodingException
+ */
+ @Test
+ public void testDisplayFromAgent() 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);
+ input.addmember(OIDCInitiatorConstants.DISPLAY).string("page");
+ 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);
+ }
+
/**
* Decode an encoded response and run sanity checks against it.
*
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AbstractOIDCAuthenticationRequestMessageHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AbstractOIDCAuthenticationRequestMessageHandler.java
deleted file mode 100644
index a8771f8..0000000
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AbstractOIDCAuthenticationRequestMessageHandler.java
+++ /dev/null
@@ -1,94 +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.messaging.impl;
-
-import java.util.function.Function;
-
-import javax.annotation.Nonnull;
-
-import org.opensaml.messaging.context.MessageContext;
-import org.opensaml.messaging.handler.AbstractMessageHandler;
-import org.opensaml.messaging.handler.MessageHandlerException;
-import org.slf4j.Logger;
-
-import net.shibboleth.oidc.profile.core.OIDCAuthenticationRequest;
-import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
-import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.primitive.LoggerFactory;
-
-/**
- * An abstract message handler that makes available the {@link OIDCAuthenticationRequest}.
- */
-public abstract class AbstractOIDCAuthenticationRequestMessageHandler extends AbstractMessageHandler {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(AbstractOIDCAuthenticationRequestMessageHandler.class);
-
- /** Strategy used to locate the {@link OIDCAuthenticationRequest}. */
- @Nonnull private Function<MessageContext, OIDCAuthenticationRequest> authenticationRequestLookupStrategy;
-
-
- /** The stashed {@link OIDCAuthenticationRequest}.*/
- @NonnullBeforeExec private OIDCAuthenticationRequest authnRequest;
-
- /** Constructor.*/
- protected AbstractOIDCAuthenticationRequestMessageHandler() {
-
- authenticationRequestLookupStrategy = mc -> {
- if (mc.getMessage() instanceof final OIDCAuthenticationRequest request) {
- return request;
- }
- return null;
- };
- }
-
- /**
- * Get the authentication request.
- *
- * @return the authentication request
- */
- @NonnullBeforeExec protected OIDCAuthenticationRequest getAuthenticationRequest() {
- return authnRequest;
- }
-
- /**
- * Set the strategy used to locate the {@link OIDCAuthenticationRequest} to use.
- *
- * @param strategy lookup strategy
- */
- public void setAuthenticationRequestLookupStrategy(
- @Nonnull final Function<MessageContext, OIDCAuthenticationRequest> strategy) {
- checkSetterPreconditions();
-
- authenticationRequestLookupStrategy =
- Constraint.isNotNull(strategy, "AuthenticationRequestLookupStrategy lookup strategy cannot be null");
- }
-
- @Override
- protected boolean doPreInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
-
- authnRequest = authenticationRequestLookupStrategy.apply(messageContext);
- if (authnRequest == null) {
- log.debug("{} OIDC authentication request is null", getLogPrefix());
- throw new MessageHandlerException("OIDC authentication request is null");
- }
-
- return super.doPreInvoke(messageContext);
- }
-
-
-
-
-}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddForceAuthenticationHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddForceAuthenticationHandler.java
deleted file mode 100644
index 6e1025c..0000000
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddForceAuthenticationHandler.java
+++ /dev/null
@@ -1,75 +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.messaging.impl;
-
-import java.time.Duration;
-
-import javax.annotation.Nonnull;
-
-import org.opensaml.messaging.context.MessageContext;
-import org.opensaml.messaging.handler.MessageHandlerException;
-import org.slf4j.Logger;
-
-import com.nimbusds.oauth2.sdk.ParseException;
-import com.nimbusds.openid.connect.sdk.Prompt;
-
-import net.shibboleth.shared.primitive.LoggerFactory;
-import net.shibboleth.sp.oidc.profile.OIDCInitiatorConstants;
-
-/**
- * An action that sets the 'prompt' parameter to 'login' and max_age to 0 seconds, iff force authn was requested by the
- * upstream SP (or is overridden in the profile config).
- */
-public class AddForceAuthenticationHandler extends AbstractOIDCAuthenticationRequestActionMessageHandler {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(AddForceAuthenticationHandler.class);
-
- @Override protected void doInvoke(@Nonnull final MessageContext messageContext)
- throws MessageHandlerException {
-
- final Integer forceAuthn = getInput().getmember(OIDCInitiatorConstants.FORCE_AUTHN).integer();
-
- if (forceAuthn != null) {
- // TODO disallow feature if set but not allowed
- try {
- getAuthenticationRequest().setPrompt(Prompt.parse(Prompt.Type.LOGIN.toString()));
- getAuthenticationRequest().setMaxAge(Duration.ofSeconds(0));
- } catch (final ParseException e) {
- // This should never happen
- throw new MessageHandlerException("Unable to honour force-authn, "
- + "setting prompt to force-login as failed", e);
- }
- return;
- }
- // Else try from Profile config
- if (getProfileConfiguration().isForceAuthn(lookupProfileRequestContext(messageContext))) {
- log.trace("{} Setting prompt=login and max_age=0 (ForceAuthn) for OIDC AuthnRequest", getLogPrefix());
- try {
- getAuthenticationRequest().setPrompt(Prompt.parse(Prompt.Type.LOGIN.toString()));
- getAuthenticationRequest().setMaxAge(Duration.ofSeconds(0));
- } catch (final ParseException e) {
- // This should never happen
- throw new MessageHandlerException("Unable to honour force-authn, "
- + "setting prompt to force-login as failed", e);
- }
- } else {
- log.trace("{} No ForceAuthn requirement, so no prompt or max_age set", getLogPrefix());
- }
- }
-
-
-
-}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddNonceHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddNonceHandler.java
deleted file mode 100644
index 948a0b0..0000000
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddNonceHandler.java
+++ /dev/null
@@ -1,74 +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.messaging.impl;
-
-import java.util.function.Function;
-
-import javax.annotation.Nonnull;
-
-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.Nonce;
-
-import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.primitive.LoggerFactory;
-import net.shibboleth.sp.oidc.profile.impl.OIDCSupport;
-
-/**
- * A message handler that adds a nonce from a lookup strategy to the authentication request.
- * The injected nonce generation strategy could generate a {@literal null} nonce.
- */
-public class AddNonceHandler extends AbstractOIDCAuthenticationRequestActionMessageHandler {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(AddNonceHandler.class);
-
- /** Strategy used to generate a nonce. Could generate a {@literal null} nonce.*/
- @Nonnull private Function<ProfileRequestContext, Nonce> nonceGenerationStrategy;
-
- /** Constructor.*/
- public AddNonceHandler() {
- // Simple strategy that uses a secure random implementation to generate a nonce of length 16
- nonceGenerationStrategy = prc -> new Nonce(OIDCSupport.generateNonce(16));
- }
-
- /**
- * Set the nonce generation strategy to use.
- *
- * @param strategy the strategy
- */
- public void setNonceGenerationStrategy(@Nonnull final Function<ProfileRequestContext, Nonce> strategy) {
- checkSetterPreconditions();
-
- nonceGenerationStrategy = Constraint.isNotNull(strategy, "Nonce generation strategy can not be null");
- }
-
- @Override protected void doInvoke(@Nonnull final MessageContext messageContext)
- throws MessageHandlerException {
-
-
- getAuthenticationRequest().setNonce(
- nonceGenerationStrategy.apply(lookupProfileRequestContext(messageContext)));
-
- log.trace("{} Added nonce '{}' to authentication request",getLogPrefix(),
- getAuthenticationRequest().getNonce());
- }
-
-
-
-}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddPassiveAuthenticationHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddPassiveAuthenticationHandler.java
deleted file mode 100644
index 2a4e63b..0000000
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddPassiveAuthenticationHandler.java
+++ /dev/null
@@ -1,60 +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.messaging.impl;
-
-import javax.annotation.Nonnull;
-
-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.oauth2.sdk.ParseException;
-import com.nimbusds.openid.connect.sdk.Prompt;
-
-import net.shibboleth.idp.authn.context.AuthenticationContext;
-import net.shibboleth.shared.primitive.LoggerFactory;
-
-/**
- * A message handler that sets the 'prompt' parameter to 'none' if passive authentication has been requested by the
- * SP.
- */
-public class AddPassiveAuthenticationHandler extends AbstractOIDCAuthenticationRequestActionMessageHandler {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(AddPassiveAuthenticationHandler.class);
-
- @Override protected void doInvoke(@Nonnull final MessageContext messageContext)
- throws MessageHandlerException {
-
- final ProfileRequestContext prc = lookupProfileRequestContext(messageContext);
- boolean isPassive = false;
- if (prc != null && prc.getParent() instanceof final AuthenticationContext authnContext) {
- isPassive = authnContext.isPassive();
- }
- if (isPassive) {
- log.trace("{} Setting 'prompt=none' for OIDC AuthnRequest", getLogPrefix());
- try {
- getAuthenticationRequest().setPrompt(Prompt.parse(Prompt.Type.NONE.toString()));
- } catch (final ParseException e) {
- // This should never happen
- throw new MessageHandlerException("Unable to honour passive authentication requirement, "
- + "setting prompt to 'none' has failed", e);
- }
- } else {
- log.trace("{} No passive authentication requirement, so prompt=none has not been set", getLogPrefix());
- }
- }
-}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddRedirectURIHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddRedirectURIHandler.java
deleted file mode 100644
index 8955161..0000000
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddRedirectURIHandler.java
+++ /dev/null
@@ -1,82 +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.messaging.impl;
-
-import java.net.URI;
-import java.util.function.BiFunction;
-
-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 jakarta.servlet.http.HttpServletRequest;
-import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.shared.component.ComponentInitializationException;
-import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.primitive.LoggerFactory;
-
-/**
- * A message handler that adds a redirect_uri to the authentication request.
- */
-public class AddRedirectURIHandler extends AbstractOIDCAuthenticationRequestActionMessageHandler {
-
- /** Logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(AddRedirectURIHandler.class);
-
- /** Function to create a suitable redirect URI from the given servlet request and profile request context.*/
- @NonnullAfterInit private BiFunction<HttpServletRequest, ProfileRequestContext, URI> redirectUriCreationStrategy;
-
- /**
- * Set the creation strategy used to compute or lookup a redirect URI.
- *
- * @param strategy the creation strategy
- */
- public void setRedirectUriCreationStrategy(
- @Nullable final BiFunction<HttpServletRequest, ProfileRequestContext, URI> strategy) {
- checkSetterPreconditions();
-
- if (strategy != null) {
- redirectUriCreationStrategy =
- Constraint.isNotNull(strategy, "RedirectURI creation lookup strategy cannot be null");
- }
- }
-
- @Override
- protected void doInitialize() throws ComponentInitializationException {
- super.doInitialize();
-
- if (redirectUriCreationStrategy == null) {
- throw new ComponentInitializationException("redirectUriCreationStrategy cannot be null");
- }
- }
-
- @Override protected void doInvoke(@Nonnull final MessageContext messageContext)
- throws MessageHandlerException {
-
- final URI redirectUri =
- redirectUriCreationStrategy.apply(getHttpServletRequest(), lookupProfileRequestContext(messageContext));
- if (redirectUri == null) {
- throw new MessageHandlerException("Redirect URI could not be located or created using the strategy");
- }
- log.trace("{} Created redirect_uri '{}'", getLogPrefix(), redirectUri);
- getAuthenticationRequest().setRedirectURI(redirectUri);
-
- }
-
-}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddResponseTypeAndModeHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddResponseTypeAndModeHandler.java
deleted file mode 100644
index e19585a..0000000
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddResponseTypeAndModeHandler.java
+++ /dev/null
@@ -1,204 +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.messaging.impl;
-
-import java.util.ArrayList;
-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.slf4j.Logger;
-
-import com.nimbusds.oauth2.sdk.ResponseMode;
-import com.nimbusds.oauth2.sdk.ResponseType;
-
-import net.shibboleth.shared.primitive.LoggerFactory;
-
-/**
- * A message handler that populates the authentication request response_mode and response_type from various strategies,
- * by default from the profile configuration.
- *
- * <p>Unless explicitly set, the default response_mode for the specified response_type will be used.</p>
- */
-public class AddResponseTypeAndModeHandler extends AbstractOIDCAuthenticationRequestActionMessageHandler {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(AddResponseTypeAndModeHandler.class);
-
-
- @Override protected void doInvoke(@Nonnull final MessageContext messageContext)
- throws MessageHandlerException {
-
- final String responseTypeFromProfile =
- getProfileConfiguration().getResponseType(lookupProfileRequestContext(messageContext));
- final ResponseType responseType = parseResponseType(responseTypeFromProfile);
- if (responseType == null){
- throw new MessageHandlerException("response_type '"+responseTypeFromProfile+"' is not supported");
- }
- // Check is supported by the provider
- checkProviderSupportsResponseType(responseType);
-
- final String responseModeFromProfile =
- getProfileConfiguration().getResponseMode(lookupProfileRequestContext(messageContext));
- final ResponseMode responseModeOverride = parseResponseMode(responseModeFromProfile);
- log.trace("{} response mode override from profile config '{}', parsed as '{}'",getLogPrefix(), responseModeFromProfile,
- responseModeOverride);
-
- final ResponseMode compatibleMode = ResponseMode.resolve(null, responseType);
- if (compatibleMode == null) {
- throw new MessageHandlerException("A compatible response_mode for response_type "
- + "'"+responseType+"' could not be found");
- }
-
- checkProviderSupportsResponseMode(compatibleMode);
-
- log.trace("{} Compatible response_mode '{}' resolved from response_type '{}'", getLogPrefix(), compatibleMode,
- responseTypeFromProfile);
- getAuthenticationRequest().setDefaultResponseMode(compatibleMode);
-
- if (responseModeOverride != null && !responseModeOverride.equals(compatibleMode)) {
- log.debug("{} response_mode override '{}' exists in the profile configuration and is different than the"
- + " default mode '{}' for response_type '{}'",
- getLogPrefix(), responseModeFromProfile, compatibleMode, responseType);
-
- checkProviderSupportsResponseMode(responseModeOverride);
- getAuthenticationRequest().setResponseMode(responseModeOverride);
-
- } else {
- getAuthenticationRequest().setResponseMode(compatibleMode);
- }
-
- getAuthenticationRequest().setResponseType(responseType);
- log.trace("{} response_type '{}' selected", getLogPrefix(), getAuthenticationRequest().getResponseType());
- log.trace("{} response_mode '{}' selected", getLogPrefix(), getAuthenticationRequest().getResponseMode());
-
- }
-
- /**
- * Check the OpenID Provider supports the response_type from its metadata value response_types_supported. Throws
- * an exception if not.
- *
- * @param responseType the response_type to check is supported
- *
- * @throws MessageHandlerException if the OpenID Provider does not support the response_type
- */
- private void checkProviderSupportsResponseType(@Nonnull final ResponseType responseType)
- throws MessageHandlerException {
- final List<ResponseType> responseTypesSupported = getProviderMetadata().getResponseTypes();
- if (responseTypesSupported == null) {
- throw new MessageHandlerException("OpenID Provider has not specified supported response types "
- + "(response_types_supported). It MUST.");
- }
- if (!responseTypesSupported.contains(responseType)) {
- throw new MessageHandlerException("OpenID Provider does not support chosen response_type: "
- + responseType.toString());
- }
- }
-
- /**
- * Check the OpenID Provider supports the response_mode from its metadata value response_modes_supported. Throws
- * an exception if not.
- *
- * @param responseMode the response_mode to check is supported
- *
- * @throws MessageHandlerException if the OpenID Provider does not support the response_mode
- */
- private void checkProviderSupportsResponseMode(@Nonnull final ResponseMode responseMode)
- throws MessageHandlerException {
- final List<ResponseMode> responseModesSupportedOP = getProviderMetadata().getResponseModes();
- final List<ResponseMode> responseModesSupported = new ArrayList<>(2);
- if (responseModesSupportedOP == null || responseModesSupportedOP.isEmpty()) {
- // Add the defaults from the specification
- responseModesSupported.add(ResponseMode.QUERY);
- responseModesSupported.add(ResponseMode.FRAGMENT);
- } else {
- responseModesSupportedOP.forEach(responseModesSupported::add);
- }
- if (!responseModesSupported.contains(responseMode)) {
- throw new MessageHandlerException("OpenID Provider does not support chosen response_mode: "
- + responseMode.toString());
- }
-
- }
-
- /**
- * Parse the response_type into a known {@link ResponseType}.
- *
- * @param responseTypeFromProfile the response_type as a string
- *
- * @return the parsed {@link ResponseType}, or {@literal null} if the input type is unknown
- */
- @Nullable private ResponseType parseResponseType(@Nullable final String responseTypeFromProfile) {
-
- if (responseTypeFromProfile == null) {
- return null;
- }
-
- if (responseTypeFromProfile.equals(ResponseType.CODE.toString())) {
- return ResponseType.CODE;
- } else if (responseTypeFromProfile.equals(ResponseType.CODE_IDTOKEN.toString())) {
- return ResponseType.CODE_IDTOKEN;
- } else if (responseTypeFromProfile.equals(ResponseType.CODE_IDTOKEN_TOKEN.toString())) {
- return ResponseType.CODE_IDTOKEN_TOKEN;
- } else if (responseTypeFromProfile.equals(ResponseType.CODE_TOKEN.toString())) {
- return ResponseType.CODE_TOKEN;
- } else if (responseTypeFromProfile.equals(ResponseType.IDTOKEN.toString())) {
- return ResponseType.IDTOKEN;
- } else if (responseTypeFromProfile.equals(ResponseType.IDTOKEN_TOKEN.toString())) {
- return ResponseType.IDTOKEN_TOKEN;
- } else {
- return null;
- }
- }
-
- // Checkstyle: ReturnCount OFF
- /**
- * Parse the response_mode into a known {@link ResponseMode}.
- *
- * @param responseModeFromProfile the response_mode as a string
- *
- * @return the parsed {@link ResponseMode}, or {@literal null} if the input type is unknown
- */
- @Nullable private ResponseMode parseResponseMode(@Nullable final String responseModeFromProfile) {
-
- if (responseModeFromProfile == null) {
- return null;
- }
-
- if (responseModeFromProfile.equals(ResponseMode.FORM_POST.getValue())) {
- return ResponseMode.FORM_POST;
- } else if (responseModeFromProfile.equals(ResponseMode.FORM_POST_JWT.getValue())) {
- return ResponseMode.FORM_POST_JWT;
- } else if (responseModeFromProfile.equals(ResponseMode.QUERY.getValue())) {
- return ResponseMode.QUERY;
- } else if (responseModeFromProfile.equals(ResponseMode.FRAGMENT.getValue())) {
- return ResponseMode.FRAGMENT;
- } else if (responseModeFromProfile.equals(ResponseMode.FRAGMENT_JWT.getValue())) {
- return ResponseMode.FRAGMENT_JWT;
- } else if (responseModeFromProfile.equals(ResponseMode.JWT.getValue())) {
- return ResponseMode.JWT;
- } else if (responseModeFromProfile.equals(ResponseMode.QUERY_JWT.getValue())) {
- return ResponseMode.QUERY_JWT;
- } else {
- return null;
- }
- }
- // Checkstyle: ReturnCount ON
-
-
-}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractAgentAndRelyingPartyContextLookupFunction.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractAgentAndRelyingPartyContextLookupFunction.java
new file mode 100644
index 0000000..1884432
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractAgentAndRelyingPartyContextLookupFunction.java
@@ -0,0 +1,128 @@
+/*
+ * 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 javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.messaging.context.navigate.ParentContextLookup;
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.shibboleth.profile.context.navigate.messaging.AbstractRelyingPartyLookupFunction;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.sp.Agent;
+import net.shibboleth.sp.Application;
+import net.shibboleth.sp.context.AgentRequestContext;
+import net.shibboleth.sp.ddf.DDF;
+
+/**
+ *
+ * Abstract base class for a function that requires a {@link AgentRequestContext}
+ * obtained via a lookup function, by default a child of the {@link ProfileRequestContext}.
+ *
+ * @param <ResultType> return type of function
+ */
+public abstract class AbstractAgentAndRelyingPartyContextLookupFunction<ResultType>
+ extends AbstractRelyingPartyLookupFunction<ResultType>{
+
+ /** Lookup strategy for {@link AgentRequestContext}. */
+ @Nonnull private Function<MessageContext,AgentRequestContext> agentRequestContextLookupStrategy;
+
+ /** Either the input or output DDF message from the agent.*/
+ protected enum DDFDirection {
+ /** The input message from the agent.*/
+ INPUT,
+ /** The output message for the agent.*/
+ OUTPUT
+ }
+
+ protected AbstractAgentAndRelyingPartyContextLookupFunction() {
+ // By default msgCtx (up)-> ProfileRequestContext (down)-> AgentRequestContext
+ agentRequestContextLookupStrategy = new ChildContextLookup<>(AgentRequestContext.class)
+ .compose(new ParentContextLookup<>(ProfileRequestContext.class));
+ }
+
+ /**
+ * Sets the lookup strategy for the {@link AgentRequestContext}.
+ *
+ * @param strategy lookup strategy
+ */
+ public void setAgentRequestContextLookupStrategy(
+ @Nonnull final Function<MessageContext,AgentRequestContext> strategy) {
+ agentRequestContextLookupStrategy = Constraint.isNotNull(strategy,
+ "AgentRequestContext lookup strategy cannot be null");
+ }
+
+ /**
+ * Invokes the installed lookup function to locate the {@link AgentRequestContext}.
+ *
+ * @param input the message context
+ *
+ * @return the {@link AgentRequestContext} or null
+ */
+ @Nullable protected AgentRequestContext getAgentRequestContext(@Nullable final MessageContext input) {
+ return agentRequestContextLookupStrategy.apply(input);
+ }
+
+ /**
+ * Gets the {@link Agent} for this request.
+ *
+ * @return the agent
+ */
+ @Nullable public Agent getAgent(@Nullable final MessageContext input) {
+ final AgentRequestContext arc = agentRequestContextLookupStrategy.apply(input);
+ if (arc == null) {
+ return null;
+ }
+ return arc.getAgent();
+ }
+
+ /**
+ * Gets the {@link Application} for this request.
+ *
+ * @return the agent
+ */
+ @Nullable public Application getApplication(@Nullable final MessageContext input) {
+ final AgentRequestContext arc = agentRequestContextLookupStrategy.apply(input);
+ if (arc == null) {
+ return null;
+ }
+ return arc.getApplication();
+ }
+
+ /**
+ * Gets the {@link DDF} for this request, either the input from the agent or the output for the agent.
+ *
+ * @return the input or output DDF
+ */
+ @Nullable public DDF getDDF(@Nullable final MessageContext input, @Nonnull final DDFDirection direction) {
+ final AgentRequestContext arc = agentRequestContextLookupStrategy.apply(input);
+ if (arc == null) {
+ return null;
+ }
+ switch (direction) {
+ case INPUT:
+ return arc.getInput();
+ case OUTPUT:
+ return arc.getOutput();
+ default:
+ return null;
+ }
+ }
+}
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
new file mode 100644
index 0000000..3d9a4a7
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractAuthenticationRequestParameterValueMessageHandler.java
@@ -0,0 +1,195 @@
+/*
+ * 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 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.AbstractMessageHandler;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.slf4j.Logger;
+
+import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
+
+import net.shibboleth.oidc.metadata.context.OIDCProviderMetadataContext;
+import net.shibboleth.oidc.profile.core.OIDCAuthenticationRequest;
+import net.shibboleth.oidc.profile.messaging.context.OIDCPeerEntityContext;
+import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
+
+/**
+ * Base class for message handlers that process and apply values of OpenID Connect authentication request parameters.
+ *
+ * <p>
+ * This abstract class provides common functionality for locating:
+ * </p>
+ * <ul>
+ * <li>the {@link OIDCAuthenticationRequest} associated with the current
+ * {@link MessageContext},</li>
+ * <li>the {@link OIDCProviderMetadata} describing the peer OpenID Provider,</li>
+ * <li>and the parameter value to be extracted and validated against
+ * the expected Java type.</li>
+ * </ul>
+ * </p>
+ *
+ * @param <T> the authentication request parameter value type
+ */
+public abstract class AbstractAuthenticationRequestParameterValueMessageHandler<T> extends AbstractMessageHandler {
+
+ /** Class logger. */
+ @Nonnull private final Logger log =
+ LoggerFactory.getLogger(AbstractAuthenticationRequestParameterValueMessageHandler.class);
+
+ /** Strategy used to locate the {@link OIDCAuthenticationRequest}. */
+ @Nonnull private Function<MessageContext, OIDCAuthenticationRequest> authenticationRequestLookupStrategy;
+
+ /** Lookup strategy to locate the OpenID Provider metadata to use.*/
+ @Nonnull private Function<MessageContext, OIDCProviderMetadataContext> providerMetadataLookupStrategy;
+
+ @Nullable private Function<MessageContext, T> parameterValueLookupStrategy;
+
+ /** The authentication request parameter value type.*/
+ @Nonnull private Class<T> type;
+
+ /** The stashed {@link OIDCAuthenticationRequest}.*/
+ @NonnullBeforeExec private OIDCAuthenticationRequest authnRequest;
+
+ /** The stashed OpenID Provider metadata .*/
+ @NonnullBeforeExec private OIDCProviderMetadata providerMetadata;
+
+
+ /** Constructor.*/
+ protected AbstractAuthenticationRequestParameterValueMessageHandler(@Nonnull final Class<T> valueType) {
+ type = Constraint.isNotNull(valueType, "Authentication request parameter value type cannot be null");
+ authenticationRequestLookupStrategy = mc -> {
+ if (mc.getMessage() instanceof final OIDCAuthenticationRequest request) {
+ return request;
+ }
+ return null;
+ };
+ providerMetadataLookupStrategy = new ChildContextLookup<>(OIDCProviderMetadataContext.class).compose(
+ new ChildContextLookup<>(OIDCPeerEntityContext.class));
+ }
+
+ /**
+ * Get the authentication request.
+ *
+ * @return the authentication request
+ */
+ @NonnullBeforeExec protected OIDCAuthenticationRequest getAuthenticationRequest() {
+ return authnRequest;
+ }
+
+ /**
+ * 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");
+ }
+
+ /**
+ * 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 parameter value lookup strategy used to find the value to set onto the authentication request.
+ *
+ * @param strategy The parameter value lookup strategy to set.
+ */
+ public void setParameterValueLookupStrategy(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.
+ *
+ * @param context the message context to pass to the lookup function
+ *
+ * @return the parameter value
+ *
+ * @throws MessageHandlerException if the value is not the expected type
+ */
+ @Nullable protected T getParameterValue(final MessageContext context)
+ throws MessageHandlerException {
+ final var localParameterValueLookupStrategy = parameterValueLookupStrategy;
+ if (localParameterValueLookupStrategy == null) {
+ return null;
+ }
+ final Object value = localParameterValueLookupStrategy.apply(context);
+ if (value == null) {
+ return null;
+ }
+ if (type.isInstance(value)) {
+ return type.cast(value);
+ }
+ throw new MessageHandlerException("Authentication request parameter value lookup returned the "
+ + "wrong value type");
+ }
+
+ /**
+ * Set the strategy used to locate the {@link OIDCAuthenticationRequest} to use.
+ *
+ * @param strategy lookup strategy
+ */
+ public void setAuthenticationRequestLookupStrategy(
+ @Nonnull final Function<MessageContext, OIDCAuthenticationRequest> strategy) {
+ checkSetterPreconditions();
+
+ authenticationRequestLookupStrategy =
+ Constraint.isNotNull(strategy, "AuthenticationRequestLookupStrategy lookup strategy cannot be null");
+ }
+
+ @Override
+ protected boolean doPreInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+
+ authnRequest = authenticationRequestLookupStrategy.apply(messageContext);
+ if (authnRequest == null) {
+ throw new MessageHandlerException("OIDC authentication request is null");
+ }
+ 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 found for peer");
+ }
+
+ return super.doPreInvoke(messageContext);
+ }
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AbstractOIDCAuthenticationRequestActionMessageHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE.java
similarity index 98%
rename from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AbstractOIDCAuthenticationRequestActionMessageHandler.java
rename to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE.java
index 1c1fb0f..de73cd8 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AbstractOIDCAuthenticationRequestActionMessageHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE.java
@@ -12,7 +12,7 @@
* limitations under the License.
*/
-package net.shibboleth.sp.oidc.messaging.impl;
+package net.shibboleth.sp.oidc.profile.impl;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -50,7 +50,7 @@ import net.shibboleth.sp.oidc.messaging.AbstractApplicationMessageHandler;
* <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 AbstractOIDCAuthenticationRequestActionMessageHandler extends AbstractApplicationMessageHandler {
+public abstract class AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE extends AbstractApplicationMessageHandler {
/** Lookup function for parent ProfileRequestContext. */
@Nonnull private static final ParentProfileRequestContextLookup<MessageContext> PRC_LOOKUP
@@ -58,7 +58,7 @@ public abstract class AbstractOIDCAuthenticationRequestActionMessageHandler exte
/** Class logger. */
@Nonnull private final Logger log =
- LoggerFactory.getLogger(AbstractOIDCAuthenticationRequestActionMessageHandler.class);
+ LoggerFactory.getLogger(AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE.class);
/** Lookup strategy to locate the OpenID Provider metadata to use.*/
@Nonnull private Function<MessageContext, OIDCProviderMetadataContext> providerMetadataLookupStrategy;
@@ -82,7 +82,7 @@ public abstract class AbstractOIDCAuthenticationRequestActionMessageHandler exte
@NonnullBeforeExec private DDF input;
/** Constructor.*/
- protected AbstractOIDCAuthenticationRequestActionMessageHandler() {
+ protected AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE() {
providerMetadataLookupStrategy = new ChildContextLookup<>(OIDCProviderMetadataContext.class).compose(
new ChildContextLookup<>(OIDCPeerEntityContext.class));
relyingPartyContextLookupStrategy = new ChildContextLookup<>(RelyingPartyContext.class);
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractProviderMetadataLookupFunction.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractProviderMetadataLookupFunction.java
new file mode 100644
index 0000000..1e6660f
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractProviderMetadataLookupFunction.java
@@ -0,0 +1,71 @@
+/*
+ * 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 javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.BaseContext;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+
+import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
+
+import net.shibboleth.oidc.metadata.context.OIDCProviderMetadataContext;
+import net.shibboleth.oidc.profile.messaging.context.OIDCPeerEntityContext;
+import net.shibboleth.shared.logic.Constraint;
+
+/**
+ * An abstract base class for pulling out the Provider metadata
+ */
+public abstract class AbstractProviderMetadataLookupFunction<F extends BaseContext, T> implements Function<F, T> {
+
+ /** Lookup strategy to locate the OpenID Provider metadata to use.*/
+ @Nonnull private Function<MessageContext, OIDCProviderMetadataContext> providerMetadataLookupStrategy;
+
+ /** Constructor.*/
+ protected AbstractProviderMetadataLookupFunction() {
+ providerMetadataLookupStrategy = new ChildContextLookup<>(OIDCProviderMetadataContext.class).compose(
+ new ChildContextLookup<>(OIDCPeerEntityContext.class));
+ }
+
+ /**
+ * Set the lookup strategy to locate the OpenID providers metadata.
+ *
+ * @param strategy the strategy.
+ */
+ public void setProviderMetadataLookupStrategy(
+ @Nonnull final Function<MessageContext, OIDCProviderMetadataContext> strategy) {
+
+ providerMetadataLookupStrategy =
+ Constraint.isNotNull(strategy,"Provider metadata lookup strategy can not be null");
+ }
+
+ /**
+ * Gets the {@link OIDCProviderMetadata} for this request.
+ *
+ * @return the provider's metadata
+ */
+ @Nullable public OIDCProviderMetadata getProviderMetadata(@Nullable final MessageContext input) {
+ final OIDCProviderMetadataContext providerCtx = providerMetadataLookupStrategy.apply(input);
+ if (providerCtx == null) {
+ return null;
+ }
+ return providerCtx.getProviderInformation();
+ }
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AuthorizationEndpointLookupStrategy.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AuthorizationEndpointLookupStrategy.java
new file mode 100644
index 0000000..988f8ad
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AuthorizationEndpointLookupStrategy.java
@@ -0,0 +1,40 @@
+/*
+ * 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.net.URI;
+
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+
+import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
+
+/**
+ * Get the OAuth 2.0 authorization endpoint from the OpenID Provider metadata.
+ */
+public class AuthorizationEndpointLookupStrategy
+ extends AbstractProviderMetadataLookupFunction<MessageContext, URI> {
+
+ /** {@inheritDoc} */
+ @Nullable public URI apply(final MessageContext messageCtx) {
+ final OIDCProviderMetadata metadata = getProviderMetadata(messageCtx);
+ if (metadata == null) {
+ return null;
+ }
+ return metadata.getAuthorizationEndpointURI();
+ }
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/BuildPlainRequestObjectJWT.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/BuildPlainRequestObjectJWT.java
similarity index 87%
rename from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/BuildPlainRequestObjectJWT.java
rename to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/BuildPlainRequestObjectJWT.java
index 313861f..8b6cfd2 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/BuildPlainRequestObjectJWT.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/BuildPlainRequestObjectJWT.java
@@ -12,7 +12,7 @@
* limitations under the License.
*/
-package net.shibboleth.sp.oidc.messaging.impl;
+package net.shibboleth.sp.oidc.profile.impl;
import javax.annotation.Nonnull;
@@ -30,11 +30,18 @@ import net.shibboleth.shared.primitive.LoggerFactory;
* If the Request Object claims are present in the authentication request, convert them
* into a JWTClaimsSet inside a PlainJWT.
*/
-public class BuildPlainRequestObjectJWT extends AbstractOIDCAuthenticationRequestMessageHandler {
+public class BuildPlainRequestObjectJWT extends AbstractAuthenticationRequestParameterValueMessageHandler<ClaimsSet> {
/** Logger. */
@Nonnull
private final Logger log = LoggerFactory.getLogger(BuildPlainRequestObjectJWT.class);
+
+ /**
+ * Constructor.
+ */
+ protected BuildPlainRequestObjectJWT() {
+ super(ClaimsSet.class);
+ }
/** {@inheritDoc} */
@Override
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/DisplayParameterLookupStrategy.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/DisplayParameterLookupStrategy.java
new file mode 100644
index 0000000..55c0e0d
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/DisplayParameterLookupStrategy.java
@@ -0,0 +1,38 @@
+/*
+ * 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.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+
+import net.shibboleth.sp.ddf.DDF;
+import net.shibboleth.sp.oidc.profile.OIDCInitiatorConstants;
+
+/**
+ * Retrieve the 'display' parameter from the {@link DDF}.
+ */
+public class DisplayParameterLookupStrategy extends AbstractAgentAndRelyingPartyContextLookupFunction<String> {
+
+ /** {@inheritDoc} */
+ @Nullable public String apply(final MessageContext messageCtx) {
+ final DDF input = getDDF(messageCtx, DDFDirection.INPUT);
+ if (input == null) {
+ return null;
+ }
+ return input.getmember(OIDCInitiatorConstants.DISPLAY).string();
+ }
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ForceAuthnParameterLookupStrategy.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ForceAuthnParameterLookupStrategy.java
new file mode 100644
index 0000000..0f93fb7
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ForceAuthnParameterLookupStrategy.java
@@ -0,0 +1,65 @@
+/*
+ * 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.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+
+import net.shibboleth.sp.ddf.DDF;
+import net.shibboleth.sp.oidc.profile.OIDCInitiatorConstants;
+
+/**
+ * Retrieve the ForceAuthn parameter from the {@link DDF}.
+ */
+public class ForceAuthnParameterLookupStrategy extends AbstractAgentAndRelyingPartyContextLookupFunction<Boolean> {
+
+ /** {@inheritDoc} */
+ @Nullable public Boolean apply(final MessageContext messageCtx) {
+ final DDF input = getDDF(messageCtx, DDFDirection.INPUT);
+ if (input == null) {
+ return null;
+ }
+ final Integer forceAuthn = input.getmember(OIDCInitiatorConstants.FORCE_AUTHN).integer();
+
+ if (forceAuthn != null) {
+ // TODO disallow feature if set but not allowed
+// if (profileConfiguration.isFeatureDisallowed(profileRequestContext,
+// BrowserSSOProfileConfiguration.FEATURE_FORCEAUTHN)) {
+// log.warn("{} Agent disallowed from overriding ForceAuthn", getLogPrefix());
+// }
+ if (forceAuthn == 1) {
+ return true;
+ }
+ return false;
+ }
+ return false;
+ // Else try from Profile config
+// if (getProfileConfiguration().isForceAuthn(lookupProfileRequestContext(messageContext))) {
+// log.trace("{} Setting prompt=login and max_age=0 (ForceAuthn) for OIDC AuthnRequest", getLogPrefix());
+// try {
+// getAuthenticationRequest().setPrompt(Prompt.parse(Prompt.Type.LOGIN.toString()));
+// getAuthenticationRequest().setMaxAge(Duration.ofSeconds(0));
+// } catch (final ParseException e) {
+// // This should never happen
+// throw new MessageHandlerException("Unable to honour force-authn, "
+// + "setting prompt to force-login as failed", e);
+// }
+// } else {
+// log.trace("{} No ForceAuthn requirement, so no prompt or max_age set", getLogPrefix());
+// }
+ }
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/InitializeOAuth2ClientContext.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/InitializeOAuth2ClientContext.java
index d27de46..2f17886 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/InitializeOAuth2ClientContext.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/InitializeOAuth2ClientContext.java
@@ -48,6 +48,7 @@ import net.shibboleth.sp.oidc.context.OAuth2ClientContext;
* @post Add the clientId and redirect URI to the {@link OAuth2ClientContext}
*/
// TODO this mostly pulls in things from the profile config and stores them, it could just come from the profile later
+//TODO Client ID needs to come from the issuer which is in the BasicAgent of the relying party config
public class InitializeOAuth2ClientContext extends AbstractProfileAction {
/** Class logger. */
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/LoginHintLookupStrategy.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/LoginHintLookupStrategy.java
new file mode 100644
index 0000000..8f45297
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/LoginHintLookupStrategy.java
@@ -0,0 +1,38 @@
+/*
+ * 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.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+
+import net.shibboleth.sp.ddf.DDF;
+import net.shibboleth.sp.oidc.profile.OIDCInitiatorConstants;
+
+/**
+ * Retrieve the 'login_hint' parameter from the {@link DDF}.
+ */
+public class LoginHintLookupStrategy extends AbstractAgentAndRelyingPartyContextLookupFunction<String> {
+
+ /** {@inheritDoc} */
+ @Nullable public String apply(final MessageContext messageCtx) {
+ final DDF input = getDDF(messageCtx, DDFDirection.INPUT);
+ if (input == null) {
+ return null;
+ }
+ return input.getmember(OIDCInitiatorConstants.LOGIN_HINT).string();
+ }
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/MaxAgeLookupStrategy.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/MaxAgeLookupStrategy.java
new file mode 100644
index 0000000..0f00321
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/MaxAgeLookupStrategy.java
@@ -0,0 +1,44 @@
+/*
+ * 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.time.Duration;
+
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+
+import net.shibboleth.sp.ddf.DDF;
+import net.shibboleth.sp.oidc.profile.OIDCInitiatorConstants;
+
+/**
+ * Retrieve the max_age parameter from the {@link DDF}.
+ */
+public class MaxAgeLookupStrategy extends AbstractAgentAndRelyingPartyContextLookupFunction<Duration> {
+
+ /** {@inheritDoc} */
+ @Nullable public Duration apply(final MessageContext messageCtx) {
+ final DDF input = getDDF(messageCtx, DDFDirection.INPUT);
+ if (input == null) {
+ return null;
+ }
+ final Long maxAge = input.getmember(OIDCInitiatorConstants.MAX_AGE).longinteger();
+ if (maxAge == null) {
+ return null;
+ }
+ return Duration.ofSeconds(maxAge);
+ }
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/package-info.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/NonceLookupStrategy.java
similarity index 51%
copy from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/package-info.java
copy to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/NonceLookupStrategy.java
index 91d9f47..72b949d 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/package-info.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/NonceLookupStrategy.java
@@ -12,7 +12,23 @@
* limitations under the License.
*/
+package net.shibboleth.sp.oidc.profile.impl;
+
+import java.util.function.Function;
+
+import org.opensaml.messaging.context.MessageContext;
+
+import com.nimbusds.openid.connect.sdk.Nonce;
+
/**
- * Package that contains message handlers.
+ * A simple strategy that uses a secure random implementation to generate a nonce of length 16.
*/
-package net.shibboleth.sp.oidc.messaging.impl;
\ No newline at end of file
+public class NonceLookupStrategy implements Function<MessageContext, Nonce> {
+
+ /** {@inheritDoc} */
+ @Override
+ public Nonce apply(final MessageContext message) {
+ return new Nonce(OIDCSupport.generateRandom(16));
+ }
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/OIDCSupport.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/OIDCSupport.java
index 3ad6057..22066c1 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/OIDCSupport.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/OIDCSupport.java
@@ -31,13 +31,13 @@ public final class OIDCSupport {
}
/**
- * Generates a random identifier to be used as a nonce.
+ * Generates a random identifier, encoded in Hex..
*
* @param length the length of the parameter.
*
- * @return the randomly generated nonce value.
+ * @return the randomly generated Hex value.
*/
- @Nonnull public static String generateNonce(@Nonnull final Integer length) {
+ @Nonnull public static String generateRandom(@Nonnull final Integer length) {
final SecureRandom secureRandom = new SecureRandom();
final StringBuilder sb = new StringBuilder();
while(sb.length() < length){
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/PromptLookupStrategy.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/PromptLookupStrategy.java
new file mode 100644
index 0000000..5bb7962
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/PromptLookupStrategy.java
@@ -0,0 +1,54 @@
+/*
+ * 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.slf4j.Logger;
+
+import com.nimbusds.oauth2.sdk.ParseException;
+import com.nimbusds.openid.connect.sdk.Prompt;
+
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.sp.ddf.DDF;
+import net.shibboleth.sp.oidc.profile.OIDCInitiatorConstants;
+
+/**
+ * Retrieve the Prompt parameter from the {@link DDF}.
+ */
+public class PromptLookupStrategy extends AbstractAgentAndRelyingPartyContextLookupFunction<Prompt> {
+
+ /** Logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(PromptLookupStrategy.class);
+
+ /** {@inheritDoc} */
+ @Nullable public Prompt apply(final MessageContext messageCtx) {
+ final DDF input = getDDF(messageCtx, DDFDirection.INPUT);
+ if (input == null) {
+ return null;
+ }
+ final String promptFromDDF = input.getmember(OIDCInitiatorConstants.PROMPT).string();
+ try {
+ return Prompt.parse(promptFromDDF);
+ } catch (final ParseException e) {
+ // This should never happen
+ log.error("Unable parse Prompt from DDF", e);
+ return null;
+ }
+ }
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/RedirectUriLookupStrategy.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/RedirectUriLookupStrategy.java
new file mode 100644
index 0000000..72393f5
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/RedirectUriLookupStrategy.java
@@ -0,0 +1,53 @@
+/*
+ * 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.net.URI;
+import java.net.URISyntaxException;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.slf4j.Logger;
+
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.sp.ddf.DDF;
+import net.shibboleth.sp.profile.InitiatorConstants;
+
+/**
+ * Retrieve the 'redirect_uri' parameter from the 'response_url' in the {@link DDF}.
+ */
+public class RedirectUriLookupStrategy extends AbstractAgentAndRelyingPartyContextLookupFunction<URI> {
+
+ /** Logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(RedirectUriLookupStrategy.class);
+
+ /** {@inheritDoc} */
+ @Nullable public URI apply(final MessageContext messageCtx) {
+ final DDF input = getDDF(messageCtx, DDFDirection.INPUT);
+ if (input == null) {
+ return null;
+ }
+ final String responseUrlFromDDF = input.getmember(InitiatorConstants.RESPONSE_URL).string();
+ try {
+ return new URI(responseUrlFromDDF);
+ } catch (final URISyntaxException e) {
+ log.error("Unable to create a redirect URI from the response_url in the input DDF", e);
+ return null;
+ }
+ }
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ResponseModeLookupStrategy.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ResponseModeLookupStrategy.java
new file mode 100644
index 0000000..c6e2f10
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ResponseModeLookupStrategy.java
@@ -0,0 +1,96 @@
+/*
+ * 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.oauth2.sdk.ResponseMode;
+
+import net.shibboleth.oidc.profile.config.OIDCAuthenticationRelyingPartyProfileConfiguration;
+import net.shibboleth.profile.context.RelyingPartyContext;
+
+/**
+ * A lookup strategy that resolves an OpenID Connect {@link ResponseMode} from the current {@link MessageContext}.
+ * <p>
+ * This strategy inspects the active {@link RelyingPartyContext} and its associated
+ * {@link OIDCAuthenticationRelyingPartyProfileConfiguration}. If a response mode
+ * is configured in the relying party profile, it is parsed into a known
+ * {@link ResponseMode} value. If no configuration is available or the configured
+ * value does not map to a supported response mode, the lookup returns {@code null}.
+ * </p>
+ */
+public class ResponseModeLookupStrategy extends AbstractAgentAndRelyingPartyContextLookupFunction<ResponseMode> {
+
+ /** Lookup function for parent ProfileRequestContext. */
+ @Nonnull private static final ParentProfileRequestContextLookup<MessageContext> PRC_LOOKUP
+ = new ParentProfileRequestContextLookup<>();
+
+ /** {@inheritDoc} */
+ @Override
+ public ResponseMode apply(final MessageContext messageContext) {
+
+ final RelyingPartyContext rpc = getRelyingPartyContext(messageContext);
+
+ if (!(rpc != null && rpc.getProfileConfig()
+ instanceof final OIDCAuthenticationRelyingPartyProfileConfiguration rpConfig)) {
+ return null;
+ }
+ // If there is no other path, and the compiler can prove rpConfig is true, you can use it here.
+ final String responseModeFromProfile =
+ rpConfig.getResponseMode(PRC_LOOKUP.apply(messageContext));
+ return parseResponseMode(responseModeFromProfile);
+ }
+
+
+ // Checkstyle: ReturnCount OFF
+ /**
+ * Parse the response_mode into a known {@link ResponseMode}.
+ *
+ * @param responseModeFromProfile the response_mode as a string
+ *
+ * @return the parsed {@link ResponseMode}, or {@literal null} if the input type is unknown
+ */
+ @Nullable private ResponseMode parseResponseMode(@Nullable final String responseModeFromProfile) {
+
+ if (responseModeFromProfile == null) {
+ return null;
+ }
+
+ if (responseModeFromProfile.equals(ResponseMode.FORM_POST.getValue())) {
+ return ResponseMode.FORM_POST;
+ } else if (responseModeFromProfile.equals(ResponseMode.FORM_POST_JWT.getValue())) {
+ return ResponseMode.FORM_POST_JWT;
+ } else if (responseModeFromProfile.equals(ResponseMode.QUERY.getValue())) {
+ return ResponseMode.QUERY;
+ } else if (responseModeFromProfile.equals(ResponseMode.FRAGMENT.getValue())) {
+ return ResponseMode.FRAGMENT;
+ } else if (responseModeFromProfile.equals(ResponseMode.FRAGMENT_JWT.getValue())) {
+ return ResponseMode.FRAGMENT_JWT;
+ } else if (responseModeFromProfile.equals(ResponseMode.JWT.getValue())) {
+ return ResponseMode.JWT;
+ } else if (responseModeFromProfile.equals(ResponseMode.QUERY_JWT.getValue())) {
+ return ResponseMode.QUERY_JWT;
+ } else {
+ return null;
+ }
+ }
+ // Checkstyle: ReturnCount ON
+
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ResponseTypeLookupStrategy.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ResponseTypeLookupStrategy.java
new file mode 100644
index 0000000..2c28d32
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ResponseTypeLookupStrategy.java
@@ -0,0 +1,93 @@
+/*
+ * 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 com.nimbusds.oauth2.sdk.ResponseType;
+
+import net.shibboleth.oidc.profile.config.OIDCAuthenticationRelyingPartyProfileConfiguration;
+import net.shibboleth.profile.context.RelyingPartyContext;
+
+/**
+ * A lookup strategy that resolves the {@link ResponseType} to use
+ * for a relying party, based the {@link OIDCAuthenticationRelyingPartyProfileConfiguration}.
+ *
+ * A lookup strategy that resolves an OpenID Connect {@link ResponseType} from the current {@link MessageContext}.
+ * <p>
+ * This strategy inspects the active {@link RelyingPartyContext} and its associated
+ * {@link OIDCAuthenticationRelyingPartyProfileConfiguration}. If a response type
+ * is configured in the relying party profile, it is parsed into a known
+ * {@link ResponseType} value. If no configuration is available or the configured
+ * value does not map to a supported response type, the lookup returns {@code null}.
+ * </p>
+ */
+public class ResponseTypeLookupStrategy extends AbstractAgentAndRelyingPartyContextLookupFunction<ResponseType>{
+
+ /** Lookup function for parent {@link ProfileRequestContext}. */
+ @Nonnull private static final ParentProfileRequestContextLookup<MessageContext> PRC_LOOKUP
+ = new ParentProfileRequestContextLookup<>();
+
+ /** {@inheritDoc} */
+ @Override
+ public ResponseType apply(@Nullable final MessageContext messageContext) {
+ final RelyingPartyContext rpc = getRelyingPartyContext(messageContext);
+
+ if (!(rpc != null && rpc.getProfileConfig()
+ instanceof final OIDCAuthenticationRelyingPartyProfileConfiguration rpConfig)) {
+ return null;
+ }
+ // If there is no other path, and the compiler can prove rpConfig is true, you can use it here.
+ final String responseTypeFromProfile =
+ rpConfig.getResponseType(PRC_LOOKUP.apply(messageContext));
+ return parseResponseType(responseTypeFromProfile);
+ }
+
+
+ /**
+ * Parse a {@code response_type} into a known {@link ResponseType}.
+ *
+ * @param responseTypeFromProfile the response_type as a string
+ *
+ * @return the parsed {@link ResponseType}, or {@literal null} if the input type is unknown
+ */
+ @Nullable private ResponseType parseResponseType(@Nullable final String responseTypeFromProfile) {
+
+ if (responseTypeFromProfile == null) {
+ return null;
+ }
+
+ if (responseTypeFromProfile.equals(ResponseType.CODE.toString())) {
+ return ResponseType.CODE;
+ } else if (responseTypeFromProfile.equals(ResponseType.CODE_IDTOKEN.toString())) {
+ return ResponseType.CODE_IDTOKEN;
+ } else if (responseTypeFromProfile.equals(ResponseType.CODE_IDTOKEN_TOKEN.toString())) {
+ return ResponseType.CODE_IDTOKEN_TOKEN;
+ } else if (responseTypeFromProfile.equals(ResponseType.CODE_TOKEN.toString())) {
+ return ResponseType.CODE_TOKEN;
+ } else if (responseTypeFromProfile.equals(ResponseType.IDTOKEN.toString())) {
+ return ResponseType.IDTOKEN;
+ } else if (responseTypeFromProfile.equals(ResponseType.IDTOKEN_TOKEN.toString())) {
+ return ResponseType.IDTOKEN_TOKEN;
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ScopeLookupStrategy.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ScopeLookupStrategy.java
new file mode 100644
index 0000000..2e485e5
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ScopeLookupStrategy.java
@@ -0,0 +1,49 @@
+/*
+ * 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.Arrays;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.opensaml.messaging.context.MessageContext;
+
+import net.shibboleth.shared.primitive.StringSupport;
+import net.shibboleth.sp.ddf.DDF;
+import net.shibboleth.sp.oidc.profile.OIDCInitiatorConstants;
+
+/**
+ *
+ */
+public class ScopeLookupStrategy extends AbstractAgentAndRelyingPartyContextLookupFunction<Set<String>>{
+
+ /** {@inheritDoc} */
+ @Override
+ public Set<String> apply(final MessageContext messageContext) {
+ final DDF input = getDDF(messageContext, DDFDirection.INPUT);
+ if (input == null) {
+ return null;
+ }
+ final String scopeFromDDF = input.getmember(OIDCInitiatorConstants.SCOPE).string();
+ if (StringSupport.trimOrNull(scopeFromDDF) == null) {
+ return null;
+ }
+ assert scopeFromDDF != null;
+ return Arrays.stream(scopeFromDDF.split("\\s+"))
+ .filter(s -> !s.isEmpty())
+ .collect(Collectors.toUnmodifiableSet());
+ }
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/SetAuthenticationRequestTimeHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/SetAuthenticationRequestTimeHandler.java
similarity index 85%
rename from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/SetAuthenticationRequestTimeHandler.java
rename to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/SetAuthenticationRequestTimeHandler.java
index 13d802f..51bdeba 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/SetAuthenticationRequestTimeHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/SetAuthenticationRequestTimeHandler.java
@@ -12,7 +12,7 @@
* limitations under the License.
*/
-package net.shibboleth.sp.oidc.messaging.impl;
+package net.shibboleth.sp.oidc.profile.impl;
import java.time.Instant;
@@ -26,11 +26,18 @@ import net.shibboleth.shared.primitive.LoggerFactory;
/** Handler that adds the authentication request time to the authentication request.*/
-public class SetAuthenticationRequestTimeHandler extends AbstractOIDCAuthenticationRequestMessageHandler {
+public class SetAuthenticationRequestTimeHandler extends AbstractAuthenticationRequestParameterValueMessageHandler<Instant> {
/** Logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(SetAuthenticationRequestTimeHandler.class);
+ /**
+ * Constructor.
+ */
+ protected SetAuthenticationRequestTimeHandler() {
+ super(Instant.class);
+ }
+
/** {@inheritDoc} */
@Override
protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/package-info.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/StateLookupStrategy.java
similarity index 52%
copy from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/package-info.java
copy to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/StateLookupStrategy.java
index 91d9f47..60008a0 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/package-info.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/StateLookupStrategy.java
@@ -12,7 +12,22 @@
* limitations under the License.
*/
+package net.shibboleth.sp.oidc.profile.impl;
+
+import java.util.function.Function;
+
+import org.opensaml.messaging.context.MessageContext;
+
/**
- * Package that contains message handlers.
+ * A simple strategy that uses a secure random implementation to generate a state of length 32.
*/
-package net.shibboleth.sp.oidc.messaging.impl;
\ No newline at end of file
+public class StateLookupStrategy implements Function<MessageContext, String> {
+
+ /** {@inheritDoc} */
+ @Override
+ public String apply(final MessageContext message) {
+ // By default, generate a 32 character state.
+ return OIDCSupport.generateRandom(32);
+ }
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/package-info.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/package-info.java
similarity index 85%
copy from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/package-info.java
copy to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/package-info.java
index 91d9f47..2e5696f 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/package-info.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/package-info.java
@@ -13,6 +13,6 @@
*/
/**
- * Package that contains message handlers.
+ * OIDC Relying Party profile implementation classes.
*/
-package net.shibboleth.sp.oidc.messaging.impl;
\ No newline at end of file
+package net.shibboleth.sp.oidc.profile.impl;
\ No newline at end of file
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddAuthenticationContextClassReferencesHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddAuthenticationContextClassReferencesHandler.java
similarity index 93%
rename from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddAuthenticationContextClassReferencesHandler.java
rename to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddAuthenticationContextClassReferencesHandler.java
index 50410c4..f24a1e1 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddAuthenticationContextClassReferencesHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddAuthenticationContextClassReferencesHandler.java
@@ -12,7 +12,7 @@
* limitations under the License.
*/
-package net.shibboleth.sp.oidc.messaging.impl;
+package net.shibboleth.sp.oidc.profile.request.impl;
import java.security.Principal;
import java.util.List;
@@ -29,13 +29,13 @@ 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;
/**
- * A message handler that adds any authentication context class references from the those derived from the
- * profile config - which may be proxied and mapped from the original request.
+ * A message handler that adds any authentication context class references. TODO
*/
public class AddAuthenticationContextClassReferencesHandler
- extends AbstractOIDCAuthenticationRequestActionMessageHandler {
+ extends AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE {
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(AddAuthenticationContextClassReferencesHandler.class);
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddDisplayHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddDisplayHandler.java
similarity index 76%
rename from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddDisplayHandler.java
rename to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddDisplayHandler.java
index 2bb6683..538f7d7 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddDisplayHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddDisplayHandler.java
@@ -12,7 +12,7 @@
* limitations under the License.
*/
-package net.shibboleth.sp.oidc.messaging.impl;
+package net.shibboleth.sp.oidc.profile.request.impl;
import javax.annotation.Nonnull;
@@ -25,31 +25,33 @@ import com.nimbusds.openid.connect.sdk.Display;
import net.shibboleth.shared.primitive.LoggerFactory;
import net.shibboleth.shared.primitive.StringSupport;
+import net.shibboleth.sp.oidc.profile.impl.AbstractAuthenticationRequestParameterValueMessageHandler;
/**
- * Message handler that adds the optional 'display' request parameter if manually set on the profile configuration.
- *
- * @since 2.1.0
+ * Message handler that adds the optional 'display' request parameter.
*/
-public class AddDisplayHandler extends AbstractOIDCAuthenticationRequestActionMessageHandler {
+public class AddDisplayHandler extends AbstractAuthenticationRequestParameterValueMessageHandler<String> {
/** Logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(AddDisplayHandler.class);
+
+ /** Constructor. */
+ protected AddDisplayHandler() {
+ super(String.class);
+ }
@Override protected void doInvoke(@Nonnull final MessageContext messageContext)
throws MessageHandlerException {
- final String display = getProfileConfiguration().getDisplay(lookupProfileRequestContext(messageContext));
- if (StringSupport.trimOrNull(display) != null) {
+ final String display = getParameterValue(messageContext);
+ if (StringSupport.trimOrNull(display) != null) {
try {
getAuthenticationRequest().setDisplay(Display.parse(display));
log.trace("Adding 'display' request parameter value '{}'", display);
} catch (final ParseException e) {
throw new MessageHandlerException("Unable to add a 'display' value of: " + display);
}
- }
-
+ }
}
-
}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddEndpointURIHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddEndpointURIHandler.java
similarity index 68%
copy from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddEndpointURIHandler.java
copy to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddEndpointURIHandler.java
index 0606dfa..0188d6e 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddEndpointURIHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddEndpointURIHandler.java
@@ -12,7 +12,7 @@
* limitations under the License.
*/
-package net.shibboleth.sp.oidc.messaging.impl;
+package net.shibboleth.sp.oidc.profile.request.impl;
import java.net.URI;
@@ -23,24 +23,29 @@ import org.opensaml.messaging.handler.MessageHandlerException;
import org.slf4j.Logger;
import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.sp.oidc.profile.impl.AbstractAuthenticationRequestParameterValueMessageHandler;
/**
- * A message handler that adds the authorization endpoint URI from the providers metadata
- * to the under constructions authentication request. If an authorization endpoint does
+ * A message handler that adds the authorization endpoint URI. If an authorization endpoint does
* not exist, an exception is thrown.
*/
-public class AddEndpointURIHandler extends AbstractOIDCAuthenticationRequestActionMessageHandler {
+public class AddEndpointURIHandler extends AbstractAuthenticationRequestParameterValueMessageHandler<URI> {
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(AddEndpointURIHandler.class);
+ /** Constructor.*/
+ public AddEndpointURIHandler() {
+ super(URI.class);
+ }
+
@Override protected void doInvoke(@Nonnull final MessageContext messageContext)
throws MessageHandlerException {
- final URI authzEndpoint = getProviderMetadata().getAuthorizationEndpointURI();
+ final URI authzEndpoint = getParameterValue(messageContext);
if (authzEndpoint == null) {
- throw new MessageHandlerException("OAuth 2.0 Authorization Endpoint URI not found in provider metadata");
+ throw new MessageHandlerException("OAuth 2.0 authorization endpoint URI not found in provider metadata");
}
getAuthenticationRequest().setEndpointURI(authzEndpoint);
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddForceAuthenticationHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddForceAuthenticationHandler.java
new file mode 100644
index 0000000..c4ab0af
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddForceAuthenticationHandler.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.request.impl;
+
+import java.time.Duration;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.slf4j.Logger;
+
+import com.nimbusds.oauth2.sdk.ParseException;
+import com.nimbusds.openid.connect.sdk.Prompt;
+
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.sp.oidc.profile.impl.AbstractAuthenticationRequestParameterValueMessageHandler;
+
+/**
+ * An action that sets the 'prompt' parameter to 'login' and max_age to 0
+ * seconds, iff force authn was requested by the upstream SP (or is overridden
+ * in the profile config).
+ */
+public class AddForceAuthenticationHandler extends AbstractAuthenticationRequestParameterValueMessageHandler<Boolean> {
+
+ /** Class logger. */
+ @Nonnull
+ private final Logger log = LoggerFactory.getLogger(AddForceAuthenticationHandler.class);
+
+ /**
+ * Constructor.
+ */
+ protected AddForceAuthenticationHandler() {
+ super(Boolean.class);
+ }
+
+ @Override
+ protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+
+ final Boolean isForceAuthn = getParameterValue(messageContext);
+ if (isForceAuthn != null && isForceAuthn) {
+ log.trace("{} Setting prompt=login and max_age=0 (ForceAuthn) for OIDC AuthnRequest", getLogPrefix());
+ try {
+ getAuthenticationRequest().setPrompt(Prompt.parse(Prompt.Type.LOGIN.toString()));
+ getAuthenticationRequest().setMaxAge(Duration.ofSeconds(0));
+ } catch (final ParseException e) {
+ // This should never happen
+ throw new MessageHandlerException(
+ "Unable to honour force-authn, " + "setting prompt to force-login as failed", e);
+ }
+ } else {
+ log.trace("{} No ForceAuthn requirement, so no prompt or max_age set", getLogPrefix());
+ }
+
+ }
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddLoginHintHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddLoginHintHandler.java
similarity index 72%
rename from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddLoginHintHandler.java
rename to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddLoginHintHandler.java
index c4482bc..0eda163 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddLoginHintHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddLoginHintHandler.java
@@ -12,7 +12,7 @@
* limitations under the License.
*/
-package net.shibboleth.sp.oidc.messaging.impl;
+package net.shibboleth.sp.oidc.profile.request.impl;
import javax.annotation.Nonnull;
@@ -21,19 +21,23 @@ import org.opensaml.messaging.handler.MessageHandlerException;
import org.slf4j.Logger;
import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.sp.oidc.profile.impl.AbstractAuthenticationRequestParameterValueMessageHandler;
-/** Message handler that adds the login_hint parameter based on any defined in the profile configuration.*/
-public class AddLoginHintHandler extends AbstractOIDCAuthenticationRequestActionMessageHandler {
+/** Message handler that adds the login_hint parameter.*/
+public class AddLoginHintHandler extends AbstractAuthenticationRequestParameterValueMessageHandler<String> {
/** Logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(AddLoginHintHandler.class);
+
+ public AddLoginHintHandler() {
+ super(String.class);
+ }
@Override
protected void doInvoke(final MessageContext messageContext) throws MessageHandlerException {
- final String loginHint =
- getProfileConfiguration().getLoginHint(lookupProfileRequestContext(messageContext));
+ final String loginHint = getParameterValue(messageContext);
if (loginHint != null) {
log.trace("{} Added login_hint parameter '{}'", getLogPrefix(), loginHint);
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddMaxAgeHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddMaxAgeHandler.java
similarity index 72%
rename from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddMaxAgeHandler.java
rename to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddMaxAgeHandler.java
index edfc045..a70c9aa 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddMaxAgeHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddMaxAgeHandler.java
@@ -12,7 +12,7 @@
* limitations under the License.
*/
-package net.shibboleth.sp.oidc.messaging.impl;
+package net.shibboleth.sp.oidc.profile.request.impl;
import java.time.Duration;
@@ -23,25 +23,27 @@ import org.opensaml.messaging.handler.MessageHandlerException;
import org.slf4j.Logger;
import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.sp.oidc.profile.impl.AbstractAuthenticationRequestParameterValueMessageHandler;
-/** Message handler that adds the max_age parameter based on any defined in the profile configuration.*/
-public class AddMaxAgeHandler extends AbstractOIDCAuthenticationRequestActionMessageHandler {
+/** Message handler that adds the max_age parameter.*/
+public class AddMaxAgeHandler extends AbstractAuthenticationRequestParameterValueMessageHandler<Duration> {
/** Logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(AddMaxAgeHandler.class);
+
+ public AddMaxAgeHandler() {
+ super(Duration.class);
+ }
@Override protected void doInvoke(@Nonnull final MessageContext messageContext)
throws MessageHandlerException {
- final Duration maxAge =
- getProfileConfiguration().getMaxAuthenticationAge(lookupProfileRequestContext(messageContext));
+ final Duration maxAge = getParameterValue(messageContext);
if (maxAge != null) {
log.trace("{} Added max_age parameter '{}'", getLogPrefix(), maxAge);
getAuthenticationRequest().setMaxAge(maxAge);
- }
-
+ }
}
-
}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddEndpointURIHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddNonceHandler.java
similarity index 54%
rename from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddEndpointURIHandler.java
rename to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddNonceHandler.java
index 0606dfa..c81261e 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddEndpointURIHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddNonceHandler.java
@@ -12,9 +12,7 @@
* limitations under the License.
*/
-package net.shibboleth.sp.oidc.messaging.impl;
-
-import java.net.URI;
+package net.shibboleth.sp.oidc.profile.request.impl;
import javax.annotation.Nonnull;
@@ -22,29 +20,36 @@ import org.opensaml.messaging.context.MessageContext;
import org.opensaml.messaging.handler.MessageHandlerException;
import org.slf4j.Logger;
-import net.shibboleth.shared.primitive.LoggerFactory;
+import com.nimbusds.openid.connect.sdk.Nonce;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.sp.oidc.profile.impl.AbstractAuthenticationRequestParameterValueMessageHandler;
/**
- * A message handler that adds the authorization endpoint URI from the providers metadata
- * to the under constructions authentication request. If an authorization endpoint does
- * not exist, an exception is thrown.
+ * A message handler that adds a nonce from a lookup strategy to the authentication request.
+ * The nonce can be {@literal null}.
*/
-public class AddEndpointURIHandler extends AbstractOIDCAuthenticationRequestActionMessageHandler {
+public class AddNonceHandler extends AbstractAuthenticationRequestParameterValueMessageHandler<Nonce> {
/** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(AddEndpointURIHandler.class);
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddNonceHandler.class);
+
+ /** Constructor.*/
+ public AddNonceHandler() {
+ super(Nonce.class);
+ }
@Override protected void doInvoke(@Nonnull final MessageContext messageContext)
throws MessageHandlerException {
- final URI authzEndpoint = getProviderMetadata().getAuthorizationEndpointURI();
- if (authzEndpoint == null) {
- throw new MessageHandlerException("OAuth 2.0 Authorization Endpoint URI not found in provider metadata");
+ final Nonce nonce = getParameterValue(messageContext);
+ if (nonce != null) {
+ getAuthenticationRequest().setNonce(nonce);
+ log.trace("{} Added nonce '{}' to authentication request",getLogPrefix(),
+ getAuthenticationRequest().getNonce());
}
-
- getAuthenticationRequest().setEndpointURI(authzEndpoint);
- log.trace("{} Added authorization endpoint '{}' to authentication request",getLogPrefix(),
- getAuthenticationRequest().getEndpointURI());
}
+
+
+
}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddPCKECodeVerifierAndChallenge.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddPCKECodeVerifierAndChallenge.java
similarity index 96%
rename from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddPCKECodeVerifierAndChallenge.java
rename to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddPCKECodeVerifierAndChallenge.java
index 19d5dd0..c4a2ea1 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddPCKECodeVerifierAndChallenge.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddPCKECodeVerifierAndChallenge.java
@@ -13,7 +13,7 @@
*/
-package net.shibboleth.sp.oidc.messaging.impl;
+package net.shibboleth.sp.oidc.profile.request.impl;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -30,14 +30,13 @@ 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;
/**
* 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.
- *
- * @since 2.1.0
*/
-public class AddPCKECodeVerifierAndChallenge extends AbstractOIDCAuthenticationRequestActionMessageHandler {
+public class AddPCKECodeVerifierAndChallenge extends AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE {
/** Logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(AddPCKECodeVerifierAndChallenge.class);
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddPromptHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddPromptHandler.java
new file mode 100644
index 0000000..65ee9b5
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddPromptHandler.java
@@ -0,0 +1,54 @@
+/*
+ * 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.request.impl;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.slf4j.Logger;
+
+import com.nimbusds.openid.connect.sdk.Prompt;
+
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.sp.oidc.profile.impl.AbstractAuthenticationRequestParameterValueMessageHandler;
+
+/**
+ * A message handler that sets the 'prompt' parameter to 'none' if passive
+ * authentication has been requested by the SP.
+ */
+public class AddPromptHandler extends AbstractAuthenticationRequestParameterValueMessageHandler<Prompt> {
+
+ /** Class logger. */
+ @Nonnull
+ private final Logger log = LoggerFactory.getLogger(AddPromptHandler.class);
+
+ /** Constructor.*/
+ public AddPromptHandler() {
+ super(Prompt.class);
+ }
+
+ @Override
+ protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+
+ final Prompt prompt = getParameterValue(messageContext);
+ if (prompt != null) {
+ if (log.isTraceEnabled()) {
+ log.trace("{} Setting 'prompt={}'", getLogPrefix(), prompt.toString());
+ }
+ getAuthenticationRequest().setPrompt(prompt);
+ }
+ }
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddRedirectURIHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddRedirectURIHandler.java
new file mode 100644
index 0000000..f7a073f
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddRedirectURIHandler.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.request.impl;
+
+import java.net.URI;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.slf4j.Logger;
+
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.sp.oidc.profile.impl.AbstractAuthenticationRequestParameterValueMessageHandler;
+
+/**
+ * A message handler that adds a redirect_uri to the authentication request.
+ */
+public class AddRedirectURIHandler extends AbstractAuthenticationRequestParameterValueMessageHandler<URI> {
+
+ /** Logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddRedirectURIHandler.class);
+//
+// /** Function to create a suitable redirect URI from the given servlet request and profile request context.*/
+// @NonnullAfterInit private BiFunction<HttpServletRequest, ProfileRequestContext, URI> redirectUriCreationStrategy;
+
+ /** Constructor.*/
+ public AddRedirectURIHandler() {
+ super(URI.class);
+ }
+
+ @Override protected void doInvoke(@Nonnull final MessageContext messageContext)
+ throws MessageHandlerException {
+
+ final URI redirectUri = getParameterValue(messageContext);
+ if (redirectUri == null) {
+ throw new MessageHandlerException("Redirect URI could not be located or created using the strategy");
+ }
+ log.trace("{} Created redirect_uri '{}'", getLogPrefix(), redirectUri);
+ getAuthenticationRequest().setRedirectURI(redirectUri);
+
+ }
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddRequestedClaimsHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddRequestedClaimsHandler.java
similarity index 94%
rename from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddRequestedClaimsHandler.java
rename to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddRequestedClaimsHandler.java
index 9cd6a3e..312da18 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddRequestedClaimsHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddRequestedClaimsHandler.java
@@ -12,7 +12,7 @@
* limitations under the License.
*/
-package net.shibboleth.sp.oidc.messaging.impl;
+package net.shibboleth.sp.oidc.profile.request.impl;
import java.util.function.Function;
@@ -28,6 +28,7 @@ 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;
@@ -39,7 +40,7 @@ import net.shibboleth.shared.primitive.LoggerFactory;
* <p>Also records in the request whether the upstream 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 AbstractOIDCAuthenticationRequestActionMessageHandler {
+public class AddRequestedClaimsHandler extends AbstractOIDCAuthenticationRequestActionMessageHandlerNOPE {
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(AddRequestedClaimsHandler.class);
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddResponseModeHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddResponseModeHandler.java
new file mode 100644
index 0000000..f0dfc3a
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddResponseModeHandler.java
@@ -0,0 +1,104 @@
+/*
+ * 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.request.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.slf4j.Logger;
+
+import com.nimbusds.oauth2.sdk.ResponseMode;
+
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.sp.oidc.profile.impl.AbstractAuthenticationRequestParameterValueMessageHandler;
+
+/**
+ * A message handler that populates the authentication request response_type.
+ */
+public class AddResponseModeHandler extends AbstractAuthenticationRequestParameterValueMessageHandler<ResponseMode> {
+
+ /** Logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddResponseModeHandler.class);
+
+ /** Constructor.*/
+ public AddResponseModeHandler() {
+ super(ResponseMode.class);
+ }
+
+ @Override protected void doInvoke(@Nonnull final MessageContext messageContext)
+ throws MessageHandlerException {
+
+ final ResponseMode responseModeFromLookup = getParameterValue(messageContext);
+
+ log.trace("{} response mode configured as '{}'",getLogPrefix(), responseModeFromLookup);
+
+ final ResponseMode compatibleMode = ResponseMode.resolve(null, getAuthenticationRequest().getResponseType());
+ if (compatibleMode == null) {
+ throw new MessageHandlerException("A compatible response_mode for response_type "
+ + "'"+getAuthenticationRequest().getResponseType()+"' could not be found");
+ }
+
+ checkProviderSupportsResponseMode(compatibleMode);
+
+ log.trace("{} Compatible response_mode '{}' resolved from response_type '{}'", getLogPrefix(), compatibleMode,
+ getAuthenticationRequest().getResponseType());
+
+ if (responseModeFromLookup != null && !responseModeFromLookup.equals(compatibleMode)) {
+ log.debug("{} response_mode override '{}' exists from configuration and is different than the"
+ + " default mode '{}' for response_type '{}'",
+ getLogPrefix(), responseModeFromLookup, compatibleMode,
+ getAuthenticationRequest().getResponseType());
+
+ checkProviderSupportsResponseMode(responseModeFromLookup);
+ getAuthenticationRequest().setResponseMode(responseModeFromLookup);
+
+ } else {
+ getAuthenticationRequest().setResponseMode(compatibleMode);
+ }
+
+ log.trace("{} response_mode '{}' selected", getLogPrefix(), getAuthenticationRequest().getResponseMode());
+ }
+
+ /**
+ * Check the OpenID Provider supports the response_mode from its metadata value response_modes_supported. Throws
+ * an exception if not.
+ *
+ * @param responseMode the response_mode to check is supported
+ *
+ * @throws MessageHandlerException if the OpenID Provider does not support the response_mode
+ */
+ private void checkProviderSupportsResponseMode(@Nonnull final ResponseMode responseMode)
+ throws MessageHandlerException {
+ final List<ResponseMode> responseModesSupportedOP = getProviderMetadata().getResponseModes();
+ final List<ResponseMode> responseModesSupported = new ArrayList<>(2);
+ if (responseModesSupportedOP == null || responseModesSupportedOP.isEmpty()) {
+ // Add the defaults from the specification
+ responseModesSupported.add(ResponseMode.QUERY);
+ responseModesSupported.add(ResponseMode.FRAGMENT);
+ } else {
+ responseModesSupportedOP.forEach(responseModesSupported::add);
+ }
+ if (!responseModesSupported.contains(responseMode)) {
+ throw new MessageHandlerException("OpenID Provider does not support chosen response_mode: "
+ + responseMode.toString());
+ }
+
+ }
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddResponseTypeHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddResponseTypeHandler.java
new file mode 100644
index 0000000..2e54188
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddResponseTypeHandler.java
@@ -0,0 +1,114 @@
+/*
+ * 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.request.impl;
+
+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.slf4j.Logger;
+
+import com.nimbusds.oauth2.sdk.ResponseMode;
+import com.nimbusds.oauth2.sdk.ResponseType;
+
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.sp.oidc.profile.impl.AbstractAuthenticationRequestParameterValueMessageHandler;
+
+/**
+ * A message handler that populates the authentication request response_type.
+ */
+public class AddResponseTypeHandler extends AbstractAuthenticationRequestParameterValueMessageHandler<ResponseType> {
+
+ /** Logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddResponseTypeHandler.class);
+
+ /** Constructor.*/
+ public AddResponseTypeHandler() {
+ super(ResponseType.class);
+ }
+
+ @Override protected void doInvoke(@Nonnull final MessageContext messageContext)
+ throws MessageHandlerException {
+
+ final ResponseType responseType = getParameterValue(messageContext);
+ if (responseType == null){
+ throw new MessageHandlerException("response_type '"+responseType+"' is not supported");
+ }
+ checkProviderSupportsResponseType(responseType);
+
+ getAuthenticationRequest().setResponseType(responseType);
+ log.trace("{} response_type '{}' selected", getLogPrefix(), getAuthenticationRequest().getResponseType());
+ }
+
+ /**
+ * Check the OpenID Provider supports the response_type from its metadata value response_types_supported. Throws
+ * an exception if not.
+ *
+ * @param responseType the response_type to check is supported
+ *
+ * @throws MessageHandlerException if the OpenID Provider does not support the response_type
+ */
+ private void checkProviderSupportsResponseType(@Nonnull final ResponseType responseType)
+ throws MessageHandlerException {
+ final List<ResponseType> responseTypesSupported = getProviderMetadata().getResponseTypes();
+ if (responseTypesSupported == null) {
+ throw new MessageHandlerException("OpenID Provider has not specified supported response types "
+ + "(response_types_supported). It MUST.");
+ }
+ if (!responseTypesSupported.contains(responseType)) {
+ throw new MessageHandlerException("OpenID Provider does not support chosen response_type: "
+ + responseType.toString());
+ }
+ }
+
+
+ // Checkstyle: ReturnCount OFF
+ /**
+ * Parse the response_mode into a known {@link ResponseMode}.
+ *
+ * @param responseModeFromProfile the response_mode as a string
+ *
+ * @return the parsed {@link ResponseMode}, or {@literal null} if the input type is unknown
+ */
+ @Nullable private ResponseMode parseResponseMode(@Nullable final String responseModeFromProfile) {
+
+ if (responseModeFromProfile == null) {
+ return null;
+ }
+
+ if (responseModeFromProfile.equals(ResponseMode.FORM_POST.getValue())) {
+ return ResponseMode.FORM_POST;
+ } else if (responseModeFromProfile.equals(ResponseMode.FORM_POST_JWT.getValue())) {
+ return ResponseMode.FORM_POST_JWT;
+ } else if (responseModeFromProfile.equals(ResponseMode.QUERY.getValue())) {
+ return ResponseMode.QUERY;
+ } else if (responseModeFromProfile.equals(ResponseMode.FRAGMENT.getValue())) {
+ return ResponseMode.FRAGMENT;
+ } else if (responseModeFromProfile.equals(ResponseMode.FRAGMENT_JWT.getValue())) {
+ return ResponseMode.FRAGMENT_JWT;
+ } else if (responseModeFromProfile.equals(ResponseMode.JWT.getValue())) {
+ return ResponseMode.JWT;
+ } else if (responseModeFromProfile.equals(ResponseMode.QUERY_JWT.getValue())) {
+ return ResponseMode.QUERY_JWT;
+ } else {
+ return null;
+ }
+ }
+ // Checkstyle: ReturnCount ON
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddScopesHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddScopesHandler.java
similarity index 72%
rename from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddScopesHandler.java
rename to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddScopesHandler.java
index 97794db..66d7fbd 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddScopesHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddScopesHandler.java
@@ -12,7 +12,7 @@
* limitations under the License.
*/
-package net.shibboleth.sp.oidc.messaging.impl;
+package net.shibboleth.sp.oidc.profile.request.impl;
import java.util.Set;
@@ -23,21 +23,28 @@ import org.opensaml.messaging.handler.MessageHandlerException;
import org.slf4j.Logger;
import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.sp.oidc.profile.impl.AbstractAuthenticationRequestParameterValueMessageHandler;
/**
- * A message handler that adds the scopes from the profile request object to the authentication request.
+ * A message handler that adds OAuth 2.0 scopes to the authentication request.
*/
-public class AddScopesHandler extends AbstractOIDCAuthenticationRequestActionMessageHandler {
+public class AddScopesHandler extends AbstractAuthenticationRequestParameterValueMessageHandler<Set<String>> {
+ /**
+ * Constructor.
+ */
+ protected AddScopesHandler() {
+ super((Class)Set.class);
+ }
+
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(AddScopesHandler.class);
@Override
protected void doInvoke(@Nonnull final MessageContext messageContext)
throws MessageHandlerException {
-
- final Set<String> scopes = getProfileConfiguration().getScopes(lookupProfileRequestContext(messageContext));
+ final Set<String> scopes = getParameterValue(messageContext);
if (scopes != null && !scopes.isEmpty()) {
scopes.forEach(s -> getAuthenticationRequest().getScope().add(s));
}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddStateHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddStateHandler.java
similarity index 62%
rename from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddStateHandler.java
rename to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddStateHandler.java
index a9067a3..8b1e0cb 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/AddStateHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/AddStateHandler.java
@@ -12,12 +12,9 @@
* limitations under the License.
*/
-package net.shibboleth.sp.oidc.messaging.impl;
-
-import java.util.function.Function;
+package net.shibboleth.sp.oidc.profile.request.impl;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import org.opensaml.messaging.context.MessageContext;
import org.opensaml.messaging.handler.MessageHandlerException;
@@ -27,14 +24,22 @@ import com.nimbusds.oauth2.sdk.id.State;
import com.nimbusds.openid.connect.sdk.claims.ClaimsSet;
import net.shibboleth.shared.primitive.LoggerFactory;
-import net.shibboleth.sp.oidc.profile.impl.OIDCSupport;
+import net.shibboleth.sp.oidc.profile.impl.AbstractAuthenticationRequestParameterValueMessageHandler;
/**
- * Add state to the authentication request URL and the request object claims (if present).
- * By default this is generated by concatenating the Hex value of the spring webflow execution
+ * Add an OAuth 2.0 / OpenID Connect {@code state} value to the authentication request URL and the request object
+ * claims (if present). By default this is generated by concatenating the Hex value of the spring webflow execution
* key with a secure random 32 character nonce.
- * */
-public class AddStateHandler extends AbstractOIDCAuthenticationRequestMessageHandler {
+ *
+ * * <p>
+ * The {@code state} parameter helps prevent cross-site request forgery
+ * (CSRF) attacks and can be used by clients to maintain request
+ * integrity.
+ * </p>
+ *
+ */
+//TODO This need thinking about in the case of the RP-Full.
+public class AddStateHandler extends AbstractAuthenticationRequestParameterValueMessageHandler<String> {
/** The 'state' claim name.*/
@Nonnull private static final String STATE_CLAIM = "state";
@@ -42,35 +47,17 @@ public class AddStateHandler extends AbstractOIDCAuthenticationRequestMessageHan
/** Logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(AddStateHandler.class);
- /** Function to create a suitable 'state' to add to the authentication request.*/
- @Nonnull private Function<MessageContext, String> stateGenerationStrategy;
/** Constructor.*/
public AddStateHandler() {
- // By default, generate state a 32 character nonce.
- stateGenerationStrategy = msg -> OIDCSupport.generateNonce(32);
- }
-
- /**
- * Set the creation strategy used to compute the 'state'.
- *
- * @param strategy the creation strategy
- */
- public void setStateGenerationStrategy(
- @Nullable final Function<MessageContext, String> strategy) {
- checkSetterPreconditions();
-
- if (strategy != null) {
- stateGenerationStrategy = strategy;
- }
-
+ super(String.class);
}
/** {@inheritDoc} */
@Override
protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
- final String stateString = stateGenerationStrategy.apply(messageContext);
+ final String stateString = getParameterValue(messageContext);
if (stateString == null) {
throw new MessageHandlerException("Generated state was null");
}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/package-info.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/package-info.java
similarity index 80%
rename from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/package-info.java
rename to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/package-info.java
index 91d9f47..c6bfa07 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/messaging/impl/package-info.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/request/impl/package-info.java
@@ -13,6 +13,6 @@
*/
/**
- * Package that contains message handlers.
+ * Temporary OIDC profile implementation classes. These will be moved into oidc-common.
*/
-package net.shibboleth.sp.oidc.messaging.impl;
\ No newline at end of file
+package net.shibboleth.sp.oidc.profile.request.impl;
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list