[java-plugin-shibd-oidc] 06/09: WIP: Logout
Codeberg
noreply at shibboleth.net
Mon Jul 13 16:24:21 UTC 2026
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch dev/JSHIBDOIDC-28
in repository java-plugin-shibd-oidc.
View the commit online:
https://codeberg.org/Shibboleth/java-plugin-shibd-oidc/commit/e69704bcfed738cafaf3d0fa4b70f6878dafaf15
commit e69704bcfed738cafaf3d0fa4b70f6878dafaf15
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Fri Jul 3 14:30:13 2026 +0100
WIP: Logout
- Logout flow to redirect. Supports post if configured.
- Still some handlers are not adding logout options
- Some other minor cleanups to classes and existing flows.
---
.../sp/oidc/context/OIDCLogoutContext.java | 3 +-
.../sp/oidc/profile/LogoutRequestStateData.java | 31 ++++
.../config/navigate/ClientIDLookupStrategy.java | 61 +++++++
.../navigate/IDTokenHintLookupStrategy.java | 72 ++++++++
.../net/shibboleth/sp/oidc/testing/TestHelper.java | 2 +
.../idp/flows/sp/consumer/oidc/oidc-beans.xml | 11 --
.../idp/flows/sp/initiator/oidc/oidc-beans.xml | 30 ++--
.../idp/flows/sp/initiator/oidc/oidc-flow.xml | 3 +-
.../flows/sp/logout/consumer/oidc/oidc-beans.xml | 191 +--------------------
.../flows/sp/logout/initiator/oidc/oidc-beans.xml | 108 +++++++++---
.../flows/sp/logout/initiator/oidc/oidc-flow.xml | 17 +-
.../shibboleth/idp/flows/sp/oidc-common-beans.xml | 11 +-
.../resources/templates/oidc-request-form-post.vm | 65 +++++++
.../src/test/resources/logback-flow-test.xml | 4 +
.../idp/module/conf/sp/oidc-test-agents.xml | 2 +-
...tLogoutRequestParameterValueMessageHandler.java | 2 +-
...ata.java => AddClientAddressToStateAction.java} | 102 ++++-------
.../sp/oidc/profile/impl/AddClientIDHandler.java | 10 +-
.../oidc/profile/impl/AddIDTokenHintHandler.java | 43 ++++-
...nHintHandler.java => AddLogoutHintHandler.java} | 18 +-
.../impl/AddPostLogoutRedirectURIHandler.java | 3 +
...ticationStateData.java => CreateStateData.java} | 33 +---
.../impl/InitializeOAuth2ClientContext.java | 36 +---
.../impl/InitializeOutboundMessageContext.java | 2 -
.../impl/LogoutRequestStateForStorageStrategy.java | 40 +++++
.../sp/oidc/profile/impl/PreserveOAuthState.java | 68 ++++++++
.../impl/CreateAuthenticationStateDataTest.java | 20 +--
27 files changed, 555 insertions(+), 433 deletions(-)
diff --git a/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/context/OIDCLogoutContext.java b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/context/OIDCLogoutContext.java
index 0c023e5..e56119f 100644
--- a/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/context/OIDCLogoutContext.java
+++ b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/context/OIDCLogoutContext.java
@@ -21,7 +21,8 @@ import org.opensaml.messaging.context.BaseContext;
import com.nimbusds.jwt.JWT;
/**
- * Context to handle state for OIDC logout flows.
+ * Context to handle state for OIDC logout flows. Typically information that has been passed up in session data
+ * by the Agent.
*/
public class OIDCLogoutContext extends BaseContext {
diff --git a/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/LogoutRequestStateData.java b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/LogoutRequestStateData.java
new file mode 100644
index 0000000..b5eefd9
--- /dev/null
+++ b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/LogoutRequestStateData.java
@@ -0,0 +1,31 @@
+/*
+ * 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;
+
+import javax.annotation.concurrent.NotThreadSafe;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+import net.shibboleth.sp.state.StateData;
+
+/**
+ * A DTO class that carries OIDC specific logout request information that needs to be recovered to validate the
+ * logout response. This class is designed for JSON serialization and deserialization for storage.
+ */
+ at JsonInclude(JsonInclude.Include.NON_NULL)
+ at NotThreadSafe
+public class LogoutRequestStateData extends StateData {
+
+}
diff --git a/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/config/navigate/ClientIDLookupStrategy.java b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/config/navigate/ClientIDLookupStrategy.java
new file mode 100644
index 0000000..fbd072d
--- /dev/null
+++ b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/config/navigate/ClientIDLookupStrategy.java
@@ -0,0 +1,61 @@
+/*
+ * 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.config.navigate;
+
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.profile.context.navigate.ParentProfileRequestContextLookup;
+
+import net.shibboleth.shared.annotation.ParameterName;
+import net.shibboleth.shared.logic.Constraint;
+
+/**
+ * A lookup strategy that locates the ClientID, used in a logout request.
+ */
+public class ClientIDLookupStrategy implements Function<MessageContext, String> {
+
+ /** Lookup function for parent {@link ProfileRequestContext}. */
+ @Nonnull private static final ParentProfileRequestContextLookup<MessageContext> PRC_LOOKUP
+ = new ParentProfileRequestContextLookup<>();
+
+ /** Strategy used to obtain the request issuer value. */
+ @Nonnull private final Function<ProfileRequestContext,String> issuerLookupStrategy;
+
+ /**
+ * Constructor.
+ *
+ * @param strategy strategy to find the logout context
+ */
+ public ClientIDLookupStrategy(@ParameterName(name = "issuerLookupStrategy")
+ @Nonnull final Function<ProfileRequestContext, String> strategy) {
+ issuerLookupStrategy = Constraint.isNotNull(strategy,
+ "IssuerLookupStrategy can not be null");
+ }
+
+
+ @Override
+ @Nullable public String apply(@Nullable final MessageContext prc) {
+ if (prc == null) {
+ return null;
+ }
+ return issuerLookupStrategy.apply(PRC_LOOKUP.apply(prc));
+ }
+
+}
diff --git a/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/context/navigate/IDTokenHintLookupStrategy.java b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/context/navigate/IDTokenHintLookupStrategy.java
new file mode 100644
index 0000000..5bf0c56
--- /dev/null
+++ b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/profile/context/navigate/IDTokenHintLookupStrategy.java
@@ -0,0 +1,72 @@
+/*
+ * 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.context.navigate;
+
+import java.util.function.Function;
+
+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.jwt.JWT;
+
+import net.shibboleth.shared.annotation.ParameterName;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.sp.oidc.context.OIDCLogoutContext;
+
+/**
+ * A lookup strategy that locates the ID Token, used as a hint in a logout request, from the {@link OIDCLogoutContext}.
+ */
+public class IDTokenHintLookupStrategy implements Function<MessageContext, JWT> {
+
+ /** Lookup function for parent {@link ProfileRequestContext}. */
+ @Nonnull private static final ParentProfileRequestContextLookup<MessageContext> PRC_LOOKUP
+ = new ParentProfileRequestContextLookup<>();
+
+ /**
+ * Strategy used to locate the {@link OIDCLogoutContext}.
+ */
+ @Nonnull
+ private final Function<ProfileRequestContext, OIDCLogoutContext> logoutContextLookupStrategy;
+
+ /**
+ * Constructor.
+ *
+ * @param strategy strategy to find the logout context
+ */
+ public IDTokenHintLookupStrategy(@ParameterName(name = "oidcLogoutContextLookupStrategy")
+ @Nonnull final Function<ProfileRequestContext, OIDCLogoutContext> strategy) {
+ logoutContextLookupStrategy = Constraint.isNotNull(strategy,
+ "StateDataContextLookupStrategy can not be null");
+ }
+
+
+ @Override
+ @Nullable public JWT apply(@Nullable final MessageContext prc) {
+ if (prc == null) {
+ return null;
+ }
+ final OIDCLogoutContext logoutContext = logoutContextLookupStrategy.apply(PRC_LOOKUP.apply(prc));
+ if (logoutContext != null && logoutContext.getIdToken() != null) {
+ return logoutContext.getIdToken();
+ }
+ return null;
+
+ }
+
+}
diff --git a/sp-oidc-api/src/test/java/net/shibboleth/sp/oidc/testing/TestHelper.java b/sp-oidc-api/src/test/java/net/shibboleth/sp/oidc/testing/TestHelper.java
index f901793..7a91ee2 100644
--- a/sp-oidc-api/src/test/java/net/shibboleth/sp/oidc/testing/TestHelper.java
+++ b/sp-oidc-api/src/test/java/net/shibboleth/sp/oidc/testing/TestHelper.java
@@ -77,6 +77,7 @@ import net.shibboleth.oidc.security.credential.JWKCredential;
import net.shibboleth.shared.codec.Base64Support;
import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.sp.ddf.DDF;
+import net.shibboleth.sp.messaging.RemotedHttpServletRequest;
import net.shibboleth.sp.oidc.profile.AuthenticationRequestStateData;
import net.shibboleth.sp.profile.ConsumerConstants;
@@ -581,6 +582,7 @@ public final class TestHelper {
@Nonnull public static DDF buildLogoutInitiatorDDFInput(@Nonnull final String idToken,
@Nonnull final String tokenParam) {
final DDF root = new DDF(null).structure();
+ root.addmember(RemotedHttpServletRequest.STRUCTURE_NAME).structure();
final DDF session = root.addmember(ConsumerConstants.SESSION_OPAQUE);
session.addmember(tokenParam).string(idToken);
return root;
diff --git a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/oidc/oidc-beans.xml b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/oidc/oidc-beans.xml
index a3be0e8..81409fe 100644
--- a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/oidc/oidc-beans.xml
+++ b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/oidc/oidc-beans.xml
@@ -41,23 +41,12 @@
<bean id="OAuthStateLookup" class="net.shibboleth.sp.oidc.messaging.context.navigate.StateFromResponseLookupFunction"/>
-
<bean id="ValidateAuthenticationResponseResult" scope="prototype"
class="net.shibboleth.sp.oidc.profile.impl.ValidateAuthenticationResponseResult" />
<bean id="InitializePeerEntityContext" class="net.shibboleth.sp.oidc.profile.impl.InitializePeerEntityContext"
p:stateDataContextLookupStrategy-ref="shibboleth.ChildLookup.StateDataContext"/>
- <bean id="InitializeRelyingPartyContextFromOIDCPeer"
- class="net.shibboleth.sp.oidc.profile.impl.InitializeRelyingPartyContextFromOIDCPeer" scope="prototype" />
-
- <bean id="SelectRelyingPartyConfiguration"
- class="net.shibboleth.sp.profile.impl.SelectRelyingPartyConfiguration" scope="prototype" />
-
- <bean id="SelectProfileConfiguration"
- class="net.shibboleth.idp.profile.impl.SelectProfileConfiguration" scope="prototype"
- p:profileId-ref="shibboleth.sp.oidc.ProfileId" />
-
<!-- Build the Token endpoint client authentication method based on the inbound context -->
<bean id="InitializeOAuth2ClientAuthenticationContextHandler" parent="WebFlowInboundMessageHandlerAdaptor"
scope="prototype">
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 68f07e2..1a2f90e 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
@@ -28,10 +28,12 @@
class="net.shibboleth.sp.oidc.profile.impl.PrepareOIDCInboundMessageContext" scope="prototype"
p:relyingPartyLookupStrategy-ref="shibboleth.RelyingPartyIdLookup.Simple">
</bean>
-
- <!-- <bean id="InitializeOutboundMessageContext" class="net.shibboleth.idp.saml.profile.impl.InitializeOutboundMessageContext"
- scope="prototype" p:selfIdentityLookupStrategy-ref="shibboleth.IssuerLookup.Simple" /> -->
-
+
+ <!-- Add information pertaining to the OAuth2.0 Client (much like a self-context) -->
+ <bean id="InitializeOAuth2ClientContext" scope="prototype"
+ class="net.shibboleth.sp.oidc.profile.impl.InitializeOAuth2ClientContext"
+ p:issuerLookupStrategy-ref="shibboleth.ClientIdLookup.Simple" />
+
<bean id="InitializeAuthorizationRequest"
class="net.shibboleth.sp.oidc.profile.impl.InitializeAuthorizationRequest" scope="prototype" />
@@ -250,7 +252,7 @@
Create the Authentication State Data from the authentication request that is preserved for later recovery
in the consumer flow.
-->
- <bean id="CreateAuthenticationStateData" class="net.shibboleth.sp.oidc.profile.impl.CreateAuthenticationStateData"
+ <bean id="CreateAuthenticationStateData" class="net.shibboleth.sp.oidc.profile.impl.CreateStateData"
scope="prototype"
p:stateDataContextCreationStrategy-ref="shibboleth.ChildLookupOrCreate.StateDataContext"
p:stateDataLookupStrategy-ref="AuthenticationRequestStateForStorageStrategy"/>
@@ -262,14 +264,17 @@
<bean id="AuthenticationRequestStateForStorageStrategy" scope="prototype"
class="net.shibboleth.sp.oidc.profile.impl.AuthenticationRequestStateForStorageStrategy"
p:authenticationAuthorityLookupStrategy-ref="shibboleth.RelyingPartyIdLookup.Simple"
- p:authenticationRequestLookupStrategy-ref="shibboleth.AuthenticationRequestLookup.FromOutbound" />
+ p:authenticationRequestLookupStrategy-ref="shibboleth.AuthenticationRequestLookup.FromOutbound" />
+
+ <bean id="AddClientAddressToState" scope="prototype" class="net.shibboleth.sp.oidc.profile.impl.AddClientAddressToStateAction"
+ p:stateDataContextLookupStrategy-ref="shibboleth.ChildLookup.StateDataContext"/>
<!--
Store off the authentication state data in the state data context so it can be recovered later when processing
the response. By default, failure to store off the state will be fatal.
-->
- <bean id="PreserveState"
- class="net.shibboleth.sp.profile.PreserveStateDataAction" scope="prototype"
+ <bean id="PreserveOAuthState"
+ class="net.shibboleth.sp.oidc.profile.impl.PreserveOAuthState" scope="prototype"
p:stateDataContextLookupStrategy-ref="shibboleth.ChildLookup.StateDataContext"
p:errorFatal="%{sp.stateToken.errorsFatal:true}" />
@@ -284,15 +289,6 @@
scope="prototype">
<property name="handlers">
<list>
- <!-- Pull out the state here, rather than during processToken of the PreserveState step -->
- <bean id="AddState" class="net.shibboleth.oidc.profile.messaging.handler.impl.AddStateHandler"
- scope="prototype">
- <property name="parameterValueLookupStrategy">
- <bean class="net.shibboleth.sp.oidc.messaging.context.navigate.StateTokenLookupStrategy" scope="prototype"
- c:stateDataContextLookupStrategy-ref="shibboleth.ChildLookup.StateDataContext"/>
- </property>
- </bean>
-
<bean id="BuildPlainRequestObjectJWT"
class="net.shibboleth.oidc.profile.messaging.handler.impl.BuildPlainRequestObjectJWT"
scope="prototype" />
diff --git a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/oidc/oidc-flow.xml b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/oidc/oidc-flow.xml
index a8f3e86..0c9f8e0 100644
--- a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/oidc/oidc-flow.xml
+++ b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/oidc/oidc-flow.xml
@@ -48,7 +48,8 @@
<action-state id="BuildOutboundMessage">
<!-- Must map authentication state to a state token first, so we can add the token to the state in HandleOutboundMessage -->
<evaluate expression="CreateAuthenticationStateData"/>
- <evaluate expression="PreserveState"/>
+ <evaluate expression="AddClientAddressToState"/>
+ <evaluate expression="PreserveOAuthState"/>
<evaluate expression="PreservePostData" />
<evaluate expression="HandleOutboundMessage" />
<evaluate expression="EncodeMessage" />
diff --git a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout/consumer/oidc/oidc-beans.xml b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout/consumer/oidc/oidc-beans.xml
index 7b37f0d..ec428c1 100644
--- a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout/consumer/oidc/oidc-beans.xml
+++ b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout/consumer/oidc/oidc-beans.xml
@@ -13,195 +13,6 @@
<util:constant id="shibboleth.EndpointType"
static-field="org.opensaml.saml.saml2.metadata.SingleLogoutService.DEFAULT_ELEMENT_NAME" />
- <!-- <import resource="classpath:/META-INF/net/shibboleth/idp/flows/sp/saml2-common-beans.xml" />
-
- Dummy manager used to generate/consume the "token" operation parameter.
- <bean id="PassthroughStateManager"
- class="net.shibboleth.sp.state.impl.PassthroughStateManager"
- p:dataSealer-ref="shibboleth.DataSealer"
- p:objectMapper-ref="shibboleth.JSONObjectMapper"
- p:expiration="PT30M">
- <property name="prefix">
- <util:constant static-field="net.shibboleth.sp.saml.saml2.profile.impl.ProcessLogoutRequest.TOKEN_PREFIX" />
- </property>
- </bean>
-
- <bean id="ProcessLogoutTokenRequest"
- class="net.shibboleth.sp.saml.saml2.profile.impl.ProcessLogoutTokenRequest" scope="prototype"
- p:stateManager-ref="PassthroughStateManager" />
-
- Only applied to LogoutResponse messages.
-
- <bean id="CreateServletResponseForLogoutResponse"
- class="net.shibboleth.sp.profile.impl.CreateOutputMessage" scope="prototype"
- p:createServletResponse="true">
- <property name="activationCondition">
- <bean parent="shibboleth.Conditions.NOT" c:_0-ref="IsLogoutRequest" />
- </property>
- </bean>
-
- <bean id="RecoverStateDataForLogoutResponse"
- class="net.shibboleth.sp.profile.impl.RecoverStateData" scope="prototype"
- p:stateTokenLookupStrategy-ref="RelayStateLookup"
- p:stateDataClass="net.shibboleth.sp.saml.saml2.SAMLStateData">
- <property name="activationCondition">
- <bean parent="shibboleth.Conditions.NOT" c:_0-ref="IsLogoutRequest" />
- </property>
- </bean>
-
- <bean id="RelayStateLookup" parent="shibboleth.Functions.Compose">
- <constructor-arg name="g">
- <bean parent="shibboleth.Functions.Expression"
- c:_0="T(org.opensaml.saml.common.binding.SAMLBindingSupport).getRelayState(#input)" />
- </constructor-arg>
- <constructor-arg name="f" ref="shibboleth.MessageContextLookup.Inbound"/>
- </bean>
-
- <bean id="IsLogoutRequest" parent="shibboleth.Conditions.Expression"
- c:_0="#input.ensureInboundMessageContext().getMessage() instanceof T(org.opensaml.saml.saml2.core.LogoutRequest)" />
-
- <bean id="CheckDestinationAndIssuerHandler" class="net.shibboleth.sp.profile.impl.WebFlowMessageHandlerAdaptor" scope="prototype"
- c:executionDirection="INBOUND">
- <constructor-arg>
- <bean class="org.opensaml.messaging.handler.impl.BasicMessageHandlerChain">
- <property name="handlers">
- <list>
- <bean class="net.shibboleth.sp.saml.saml2.messaging.impl.CheckDestinationAndIssuerHandler" scope="prototype"
- p:checkDuringInit="false"
- p:httpServletRequestSupplier-ref="shibboleth.RemotedHttpServletRequestSupplier" />
- </list>
- </property>
- </bean>
- </constructor-arg>
- <property name="errorEvent">
- <util:constant static-field="org.opensaml.profile.action.EventIds.INVALID_MESSAGE" />
- </property>
- </bean>
-
- <bean id="HandleMessageEarly" class="net.shibboleth.sp.profile.impl.WebFlowMessageHandlerAdaptor" scope="prototype"
- c:executionDirection="INBOUND">
- <constructor-arg>
- <bean class="org.opensaml.messaging.handler.impl.BasicMessageHandlerChain">
- <property name="handlers">
- <list>
- <bean class="org.opensaml.messaging.handler.impl.FunctionMessageHandler" scope="prototype">
- <property name="functionLookupStrategy">
- <bean class="net.shibboleth.saml.profile.config.navigate.messaging.MessageHandlerLookupFunction" />
- </property>
- </bean>
- <bean class="org.opensaml.saml.common.binding.security.impl.ReceivedEndpointSecurityHandler" scope="prototype"
- p:checkDuringInit="false"
- p:httpServletRequestSupplier-ref="shibboleth.RemotedHttpServletRequestSupplier" />
- <bean class="org.opensaml.saml.common.binding.security.impl.MessageReplaySecurityHandler" scope="prototype"
- p:replayCache-ref="shibboleth.ReplayCache"
- p:expires="%{sp.policy.messageLifetime:PT3M}" />
- <bean class="org.opensaml.saml.common.binding.security.impl.MessageLifetimeSecurityHandler" scope="prototype"
- p:messageLifetime="%{sp.policy.messageLifetime:PT3M}"
- p:clockSkew="%{sp.policy.clockSkew:PT3M}" />
- </list>
- </property>
- </bean>
- </constructor-arg>
- <property name="errorEvent">
- <util:constant static-field="org.opensaml.profile.action.EventIds.INVALID_MESSAGE" />
- </property>
- </bean>
-
- <bean id="NotIgnoreRequestSignaturesPredicate" parent="shibboleth.Conditions.NOT">
- <constructor-arg>
- <bean class="net.shibboleth.saml.saml2.profile.config.logic.IgnoreRequestSignaturesPredicate" />
- </constructor-arg>
- </bean>
-
- <bean id="CheckSignature" class="net.shibboleth.sp.profile.impl.WebFlowMessageHandlerAdaptor" scope="prototype"
- c:executionDirection="INBOUND"
- p:activationCondition-ref="NotIgnoreRequestSignaturesPredicate">
- <constructor-arg>
- <bean class="org.opensaml.messaging.handler.impl.BasicMessageHandlerChain">
- <property name="handlers">
- <list>
- <bean class="org.opensaml.saml.saml2.binding.security.impl.SAML2HTTPRedirectDeflateSignatureSecurityHandler" scope="prototype"
- p:checkDuringInit="false"
- p:httpServletRequestSupplier-ref="shibboleth.RemotedHttpServletRequestSupplier" />
- <bean class="org.opensaml.saml.common.binding.security.impl.SAMLProtocolMessageXMLSignatureSecurityHandler" scope="prototype" />
- <bean class="org.opensaml.saml.saml2.binding.security.impl.SAML2HTTPPostSimpleSignSecurityHandler" scope="prototype"
- p:checkDuringInit="false"
- p:httpServletRequestSupplier-ref="shibboleth.RemotedHttpServletRequestSupplier"
- p:parser-ref="shibboleth.ParserPool"
- p:keyInfoResolver-ref="shibboleth.KeyInfoCredentialResolver" />
- </list>
- </property>
- </bean>
- </constructor-arg>
- <property name="errorEvent">
- <util:constant static-field="org.opensaml.profile.action.EventIds.INVALID_MESSAGE" />
- </property>
- </bean>
-
- <bean id="InboundEntityIDLookup" parent="shibboleth.Functions.Compose">
- <constructor-arg name="g">
- <bean class="org.opensaml.saml.common.messaging.context.navigate.SAMLEntityIDFunction" />
- </constructor-arg>
- <constructor-arg name="f">
- <bean class="org.opensaml.messaging.context.navigate.ChildContextLookup"
- c:type="#{ T(org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext) }" />
- </constructor-arg>
- </bean>
-
- <bean id="HandleMessageLate" class="net.shibboleth.sp.profile.impl.WebFlowMessageHandlerAdaptor" scope="prototype"
- c:executionDirection="INBOUND">
- <constructor-arg>
- <bean class="org.opensaml.messaging.handler.impl.BasicMessageHandlerChain">
- <property name="handlers">
- <list>
- <bean class="org.opensaml.messaging.handler.impl.CheckMandatoryIssuer" scope="prototype"
- p:issuerLookupStrategy-ref="InboundEntityIDLookup" />
- <bean class="org.opensaml.messaging.handler.impl.CheckMandatoryAuthentication" scope="prototype"
- p:activationCondition="%{sp.saml.logout.authenticated:true}">
- <property name="authenticationLookupStrategy">
- <bean class="org.opensaml.saml.common.messaging.context.navigate.SAMLMessageContextAuthenticationFunction" />
- </property>
- </bean>
- </list>
- </property>
- </bean>
- </constructor-arg>
- <property name="errorEvent">
- <util:constant static-field="org.opensaml.profile.action.EventIds.INVALID_MESSAGE" />
- </property>
- </bean>
-
- <bean id="PopulateDecryptionParameters"
- class="org.opensaml.profile.action.impl.PopulateDecryptionParameters" scope="prototype"
- p:recipientLookupStrategy-ref="shibboleth.IssuerLookup.Simple"
- p:configurationLookupStrategy-ref="shibboleth.DecryptionConfigurationLookup"
- p:decryptionParametersResolver-ref="shibboleth.DecryptionParametersResolver" />
-
- <bean id="DecryptNameIDs" class="org.opensaml.saml.saml2.profile.impl.DecryptNameIDs" scope="prototype" />
-
- <bean id="ProcessLogoutRequest"
- class="net.shibboleth.sp.saml.saml2.profile.impl.ProcessLogoutRequest" scope="prototype"
- p:parserPool-ref="shibboleth.ParserPool"
- p:stateManager-ref="PassthroughStateManager" />
-
- <bean id="ProcessLogoutResponse"
- class="net.shibboleth.sp.saml.saml2.profile.impl.ProcessLogoutResponse" scope="prototype" />
-
- <bean id="PopulateResponseSignatureSigningParameters"
- class="org.opensaml.saml.common.profile.impl.PopulateSignatureSigningParameters" scope="prototype"
- p:configurationLookupStrategy-ref="shibboleth.SignatureSigningConfigurationLookup"
- p:signatureSigningParametersResolver-ref="shibboleth.SignatureSigningParametersResolver"
- p:noResultIsError="false">
- <property name="activationCondition">
- <bean class="net.shibboleth.saml.profile.config.logic.SignResponsesPredicate" />
- </property>
- </bean>
-
- <bean id="CreateServletResponse"
- class="net.shibboleth.sp.profile.impl.CreateOutputMessage" scope="prototype"
- p:createServletResponse="true" />
-
- <bean id="AddLogoutResponse"
- class="net.shibboleth.sp.saml.saml2.profile.impl.AddLogoutResponse" scope="prototype" /> -->
+
</beans>
diff --git a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout/initiator/oidc/oidc-beans.xml b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout/initiator/oidc/oidc-beans.xml
index 937c0b4..70120b9 100644
--- a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout/initiator/oidc/oidc-beans.xml
+++ b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout/initiator/oidc/oidc-beans.xml
@@ -9,6 +9,8 @@
<util:constant id="shibboleth.sp.oidc.ProfileId"
static-field="net.shibboleth.oidc.profile.config.OIDCLogoutProfileConfiguration.PROFILE_ID" />
+
+ <bean id="shibboleth.sp.loggingId" class="java.lang.String" c:_0="%{sp.oidc.service.logging.token-consumer:LogoutInitiator.OIDC}" />
<import resource="classpath:/META-INF/net/shibboleth/idp/flows/sp/oidc-common-beans.xml" />
@@ -21,18 +23,6 @@
class="net.shibboleth.sp.oidc.profile.impl.PrepareOIDCInboundMessageContext" scope="prototype"
p:relyingPartyLookupStrategy-ref="shibboleth.RelyingPartyIdLookup.Simple">
</bean>
-
- <!-- <util:constant id="shibboleth.EndpointType"
- static-field="org.opensaml.saml.saml2.metadata.SingleLogoutService.DEFAULT_ELEMENT_NAME" />
-
- <bean id="AddLogoutRequest"
- class="net.shibboleth.sp.saml.saml2.profile.impl.AddLogoutRequest" scope="prototype"
- p:overwriteExisting="true">
- <property name="identifierGeneratorLookupStrategy">
- <bean class="net.shibboleth.profile.config.navigate.IdentifierGenerationStrategyLookupFunction"
- p:defaultIdentifierGenerationStrategy-ref="shibboleth.DefaultIdentifierGenerationStrategy" />
- </property>
- </bean> -->
<bean id="InitializeLogoutRequest" class="net.shibboleth.sp.oidc.profile.impl.InitializeLogoutRequest">
<property name="logoutEndpointLookupStrategy">
@@ -50,6 +40,8 @@
</property>
</bean>
+ <!-- TODO, these should be optional via RP profile config switched, but we do not have a LogoutProfile config
+ for the RP -->
<bean id="BuildLogoutRequest" parent="WebFlowOutboundMessageHandlerAdaptor" scope="prototype">
<constructor-arg>
<bean class="org.opensaml.messaging.handler.impl.BasicMessageHandlerChain">
@@ -57,13 +49,15 @@
<list>
<bean id="AddIDTokenHint" scope="prototype" parent="LogoutRequestHandler"
class="net.shibboleth.sp.oidc.profile.impl.AddIDTokenHintHandler">
- <!-- <property name="parameterValueLookupStrategy">
- <bean class="net.shibboleth.sp.oidc.profile.config.navigate.ResponseTypeLookupStrategy"
+ <property name="parameterValueLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.context.navigate.IDTokenHintLookupStrategy"
+ c:oidcLogoutContextLookupStrategy-ref="shibboleth.ChildLookup.LogoutContext"
scope="prototype" />
- </property> -->
+ </property>
</bean>
- <bean id="AddLoginHint" scope="prototype" parent="LogoutRequestHandler"
- class="net.shibboleth.sp.oidc.profile.impl.AddLoginHintHandler">
+ <!-- Should this be conditional on the ID Token Hint being present? -->
+ <bean id="AddLogoutHint" scope="prototype" parent="LogoutRequestHandler"
+ class="net.shibboleth.sp.oidc.profile.impl.AddLogoutHintHandler">
<!-- <property name="parameterValueLookupStrategy">
<bean class="net.shibboleth.sp.oidc.profile.config.navigate.ResponseTypeLookupStrategy"
scope="prototype" />
@@ -71,10 +65,11 @@
</bean>
<bean id="AddClientID" scope="prototype" parent="LogoutRequestHandler"
class="net.shibboleth.sp.oidc.profile.impl.AddClientIDHandler">
- <!-- <property name="parameterValueLookupStrategy">
- <bean class="net.shibboleth.sp.oidc.profile.config.navigate.ResponseTypeLookupStrategy"
- scope="prototype" />
- </property> -->
+ <property name="parameterValueLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.config.navigate.ClientIDLookupStrategy"
+ scope="prototype"
+ c:issuerLookupStrategy-ref="shibboleth.ClientIdLookup.Simple"/>
+ </property>
</bean>
<bean id="AddPostLogoutRedirectURI" scope="prototype" parent="LogoutRequestHandler"
class="net.shibboleth.sp.oidc.profile.impl.AddPostLogoutRedirectURIHandler">
@@ -85,10 +80,10 @@
</bean>
<bean id="AddUILocales" scope="prototype" parent="LogoutRequestHandler"
class="net.shibboleth.sp.oidc.profile.impl.AddUILocalesHandler">
- <!-- <property name="parameterValueLookupStrategy">
- <bean class="net.shibboleth.sp.oidc.profile.config.navigate.ResponseTypeLookupStrategy"
+ <property name="parameterValueLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.config.navigate.UiLocalesLookupStrategy"
scope="prototype" />
- </property> -->
+ </property>
</bean>
</list>
</property>
@@ -99,4 +94,69 @@
</property>
</bean>
+ <!--
+ Create the Authentication State Data from the authentication request that is preserved for later recovery
+ in the consumer flow.
+ -->
+ <bean id="CreateLogoutStateData" class="net.shibboleth.sp.oidc.profile.impl.CreateStateData"
+ scope="prototype"
+ p:stateDataContextCreationStrategy-ref="shibboleth.ChildLookupOrCreate.StateDataContext"
+ p:stateDataLookupStrategy-ref="LogoutRequestStateForStorageStrategy"/>
+
+ <!--
+ A strategy for creating Logout Stata Data from the logout request.
+ -->
+ <bean id="LogoutRequestStateForStorageStrategy" scope="prototype"
+ class="net.shibboleth.sp.oidc.profile.impl.LogoutRequestStateForStorageStrategy" />
+
+
+ <!--
+ Store off the authentication state data in the state data context so it can be recovered later when processing
+ the response. By default, failure to store off the state will be fatal.
+ -->
+ <bean id="PreserveOAuthState"
+ class="net.shibboleth.sp.oidc.profile.impl.PreserveOAuthState" scope="prototype"
+ p:stateDataContextLookupStrategy-ref="shibboleth.ChildLookup.StateDataContext"
+ p:errorFatal="%{sp.stateToken.errorsFatal:true}" />
+
+ <bean id="HandleOutboundMessage" class="net.shibboleth.idp.profile.impl.WebFlowMessageHandlerAdaptor"
+ scope="prototype" c:messageHandler-ref="PreEncodeMessageHandler" c:executionDirection="OUTBOUND">
+ <property name="errorEvent">
+ <util:constant static-field="org.opensaml.profile.action.EventIds.MESSAGE_PROC_ERROR" />
+ </property>
+ </bean>
+
+ <bean id="PreEncodeMessageHandler" class="org.opensaml.messaging.handler.impl.BasicMessageHandlerChain"
+ scope="prototype">
+ <property name="handlers">
+ <list>
+ </list>
+ </property>
+ </bean>
+
+ <bean id="EncodeMessage" class="net.shibboleth.sp.profile.impl.EncodeMessage" scope="prototype"
+ p:messageEncoderFactory-ref="messageEncoderFactory" />
+
+ <!-- Message Encoder factory is a prototype to allow reuse of the encoders -->
+ <bean id="messageEncoderFactory"
+ class="net.shibboleth.oidc.profile.impl.LogoutRequestMessageEncoderFactory" scope="prototype"
+ c:encoders-ref="RequestEncoders" />
+
+ <!-- List must itself be a prototype so new encoders are created per request -->
+ <util:list id="RequestEncoders" scope="prototype">
+ <ref bean="HTTPRedirectRequestEncoder" />
+ <ref bean="HTTPPostRequestEncoder" />
+ </util:list>
+
+ <bean id="HTTPRedirectRequestEncoder"
+ class="net.shibboleth.oidc.profile.encoding.impl.HTTPRedirectRequestEncoder" init-method=""
+ scope="prototype" p:httpServletResponseSupplier-ref="shibboleth.RemotedHttpServletResponseSupplier" />
+
+ <bean id="HTTPPostRequestEncoder"
+ class="net.shibboleth.oidc.profile.encoding.impl.HTTPPostRequestEncoder" init-method="" scope="prototype"
+ p:velocityEngine-ref="shibboleth.VelocityEngine"
+ p:httpServletResponseSupplier-ref="shibboleth.RemotedHttpServletResponseSupplier"
+ p:cSPDigester="#{%{idp.encoders.cspEnabled:true} ? getObject('shibboleth.CSPDigester') : null}"
+ p:cSPNonceGenerator="#{%{idp.encoders.cspEnabled:true} ? getObject('shibboleth.CSPNonce') : null}" />
+
</beans>
diff --git a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout/initiator/oidc/oidc-flow.xml b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout/initiator/oidc/oidc-flow.xml
index c35bf13..b7a92bd 100644
--- a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout/initiator/oidc/oidc-flow.xml
+++ b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout/initiator/oidc/oidc-flow.xml
@@ -13,21 +13,14 @@
<evaluate expression="SelectProfileConfiguration" />
- <evaluate expression="InitializeOutboundMessageContext" />
- <!-- <evaluate expression="InitializeOAuth2ClientContext" />-->
+ <evaluate expression="InitializeOutboundMessageContext" />
<evaluate expression="InitializeLogoutRequest" />
- <!-- <evaluate expression="InitializeMessageChannelSecurityContext" />
- <evaluate expression="PopulateBindingAndEndpointContexts" />
-
- <evaluate expression="PopulateRequestSignatureSigningParameters" />
- <evaluate expression="PopulateEncryptionParameters" />-->
<evaluate expression="BuildLogoutRequest" />
- <!-- <evaluate expression="EncryptNameIDs" /> -->
-
-<!-- <evaluate expression="HandleOutboundMessage" />
- <evaluate expression="PreserveRelayState" />
- <evaluate expression="EncodeMessage" /> -->
+ <evaluate expression="CreateLogoutStateData"/>
+ <evaluate expression="PreserveOAuthState" />
+ <evaluate expression="HandleOutboundMessage" />
+ <evaluate expression="EncodeMessage" />
<evaluate expression="'proceed'" />
<transition on="proceed" to="proceed" />
diff --git a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/oidc-common-beans.xml b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/oidc-common-beans.xml
index 5125d99..c609f4f 100644
--- a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/oidc-common-beans.xml
+++ b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/oidc-common-beans.xml
@@ -253,13 +253,12 @@
class="net.shibboleth.idp.profile.impl.SelectProfileConfiguration" scope="prototype"
p:profileId-ref="shibboleth.sp.oidc.ProfileId" />
- <!-- TODO, self context -->
+ <!--
+ We do not add self-context to the outbound message here, we construct an OAuth2ClientContext to store that and
+ other client information.
+ -->
<bean id="InitializeOutboundMessageContext"
class="net.shibboleth.sp.oidc.profile.impl.InitializeOutboundMessageContext" scope="prototype" />
-
- <bean id="InitializeOAuth2ClientContext" scope="prototype"
- class="net.shibboleth.sp.oidc.profile.impl.InitializeOAuth2ClientContext"
- p:issuerLookupStrategy-ref="shibboleth.ClientIdLookup.Simple" />
-
+
</beans>
diff --git a/sp-oidc-conf-impl/src/main/resources/templates/oidc-request-form-post.vm b/sp-oidc-conf-impl/src/main/resources/templates/oidc-request-form-post.vm
new file mode 100644
index 0000000..6ee1e87
--- /dev/null
+++ b/sp-oidc-conf-impl/src/main/resources/templates/oidc-request-form-post.vm
@@ -0,0 +1,65 @@
+##
+## Velocity Template for OIDC Form Post response mode.
+## cspDigester - Calculates base64-encoded SHA-2 hashes (call apply). Can be null for backward compatibility.
+## cspNonce - Calculates secure nonces (call generateIdentifier). Can be null for backward compatibility.
+##
+##
+#set ($onLoad = "document.forms[0].submit()")
+#if($cspDigester)
+ $response.addHeader("Content-Security-Policy","object-src 'none'; script-src 'none'; script-src-attr 'unsafe-hashes' 'sha256-$cspDigester.apply($onLoad)'")
+#end
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="utf-8" />
+</head>
+
+<body onload="$onLoad">
+ <noscript>
+ <p>
+ <strong>Note:</strong> Since your browser does not support JavaScript, you must press the Continue button once to proceed.
+ </p>
+ </noscript>
+
+ <form action="${action}" method="post">
+ <div>
+ #if($id_token_hint) <input type="hidden" name="id_token_hint" value="${id_token_hint}" />#end #if($ui_locales)
+
+ <input type="hidden" name="ui_locales" value="${ui_locales}" />#end #if($post_logout_redirect_uri)
+
+ <input type="hidden" name="post_logout_redirect_uri" value="${post_logout_redirect_uri}" />#end #if($logout_hint)
+
+ <input type="hidden" name="logout_hint" value="${logout_hint}" />#end #if($client_id)
+
+ <input type="hidden" name="client_id" value="${client_id}" />#end #if($scope)
+
+ <input type="hidden" name="scope" value="${scope}" />#end #if($response_type)
+
+ <input type="hidden" name="response_type" value="${response_type}" />#end #if($response_mode)
+
+ <input type="hidden" name="response_mode" value="${response_mode}" />#end #if($redirect_uri)
+
+ <input type="hidden" name="redirect_uri" value="${redirect_uri}" />#end #if($state)
+
+ <input type="hidden" name="state" value="${state}" />#end #if($prompt)
+
+ <input type="hidden" name="prompt" value="${prompt}" />#end #if($request)
+
+ <input type="hidden" name="request" value="${request}" />#end #if($acr_values)
+
+ <input type="hidden" name="acr_values" value="${acr_values}" />#end #if($claims)
+
+ <input type="hidden" name="claims" value="${claims}" />#end #if($nonce)
+
+ <input type="hidden" name="nonce" value="${nonce}" />#end
+ </div>
+ <noscript>
+ <div>
+ <input type="submit" value="Continue" />
+ </div>
+ </noscript>
+ </form>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/sp-oidc-conf-impl/src/test/resources/logback-flow-test.xml b/sp-oidc-conf-impl/src/test/resources/logback-flow-test.xml
index 0b70e92..a89c91c 100644
--- a/sp-oidc-conf-impl/src/test/resources/logback-flow-test.xml
+++ b/sp-oidc-conf-impl/src/test/resources/logback-flow-test.xml
@@ -26,4 +26,8 @@
<appender-ref ref="STDOUT" />
</logger>
+ <logger name="net.shibboleth.oidc" level="TRACE" additivity="false">
+ <appender-ref ref="STDOUT" />
+ </logger>
+
</configuration>
\ No newline at end of file
diff --git a/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/oidc-test-agents.xml b/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/oidc-test-agents.xml
index 60c0576..583c1bb 100644
--- a/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/oidc-test-agents.xml
+++ b/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/oidc-test-agents.xml
@@ -24,7 +24,7 @@
<set>
<bean p:id="test-oidc-application-with-default-profile" parent="shibboleth.sp.Application"/>
- <bean p:id="test-oidc-application-without-ro" parent="shibboleth.sp.Application"
+ <bean p:id="test-oidc-application-without-ro" parent="shibboleth.sp.Application"
p:profileConfigurations-ref="test.ProfileConfigurations"/>
<bean p:id="test-oidc-application-with-pkce" parent="shibboleth.sp.Application"
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractLogoutRequestParameterValueMessageHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractLogoutRequestParameterValueMessageHandler.java
index 4ae0dde..8a2ef51 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractLogoutRequestParameterValueMessageHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractLogoutRequestParameterValueMessageHandler.java
@@ -151,7 +151,7 @@ public abstract class AbstractLogoutRequestParameterValueMessageHandler<T> exten
*
* @throws MessageHandlerException if the value is not the expected type
*/
- @Nullable protected T getParameterValue(final MessageContext context)
+ @Nullable protected T getParameterValue(@Nonnull final MessageContext context)
throws MessageHandlerException {
final var localParameterValueLookupStrategy = parameterValueLookupStrategy;
if (localParameterValueLookupStrategy == null) {
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/CreateAuthenticationStateData.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddClientAddressToStateAction.java
similarity index 54%
copy from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/CreateAuthenticationStateData.java
copy to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddClientAddressToStateAction.java
index a560775..3c9e842 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/CreateAuthenticationStateData.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddClientAddressToStateAction.java
@@ -27,41 +27,30 @@ import org.slf4j.Logger;
import net.shibboleth.idp.profile.IdPEventIds;
import net.shibboleth.oidc.profile.config.OIDCSSORelyingPartyConfiguration;
import net.shibboleth.profile.context.RelyingPartyContext;
-import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
-import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.primitive.LoggerFactory;
import net.shibboleth.sp.context.StateDataContext;
import net.shibboleth.sp.ddf.DDF;
import net.shibboleth.sp.messaging.RemotedHttpServletRequest;
import net.shibboleth.sp.profile.AbstractApplicationAction;
-import net.shibboleth.sp.profile.SPConstants;
import net.shibboleth.sp.state.StateData;
/**
+ * An action that adds, if enabled in profile config, the client address to State Data.
*
- * An action that looks up {@link StateData} using a configured lookup strategy and adds it to a
- * {@link StateDataContext} obtained from the profile request context using a configured creation strategy.
- *
- * <p>In addition, the target URL is pulled out of the Agent input and added to the state data, if available, or if
- * not, from any existing state data.</p>
+ * <p>When disabled, the pre-execute step will return false and the reminder of the action will be skipped.</p>
*
* @event {@link EventIds#INVALID_PROFILE_CTX}
+ * @event {@link EventIds#INVALID_PROFILE_CONFIG}
*/
-public class CreateAuthenticationStateData extends AbstractApplicationAction {
+public class AddClientAddressToStateAction extends AbstractApplicationAction {
/** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(CreateAuthenticationStateData.class);
-
- /**
- * Lookup strategy for the contents of the state token, as stored in a {@link StateData} or subclass thereof.
- * This is augmented with other state data as defined in this action.
- */
- @NonnullAfterInit private Function<ProfileRequestContext,StateData> stateDataLookupStrategy;
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddClientAddressToStateAction.class);
- /** Strategy used to locate or create the {@link StateDataContext} to populate. */
- @Nonnull private Function<ProfileRequestContext,StateDataContext> stateDataContextCreationStrategy;
+ /** Strategy used to locate the {@link StateDataContext} to populate. */
+ @Nonnull private Function<ProfileRequestContext,StateDataContext> stateDataContextLookupStrategy;
/** Applicable stashed profile configuration. */
@NonnullBeforeExec private OIDCSSORelyingPartyConfiguration profileConfiguration;
@@ -75,8 +64,8 @@ public class CreateAuthenticationStateData extends AbstractApplicationAction {
/**
* Constructor.
*/
- public CreateAuthenticationStateData() {
- stateDataContextCreationStrategy = new ChildContextLookup<>(StateDataContext.class, true);
+ public AddClientAddressToStateAction() {
+ stateDataContextLookupStrategy = new ChildContextLookup<>(StateDataContext.class, false);
}
/**
@@ -84,38 +73,16 @@ public class CreateAuthenticationStateData extends AbstractApplicationAction {
*
* @param strategy creation strategy
*/
- public void setStateDataContextCreationStrategy(
+ public void setStateDataContextLookupStrategy(
@Nonnull final Function<ProfileRequestContext,StateDataContext> strategy) {
checkSetterPreconditions();
- stateDataContextCreationStrategy =
+ stateDataContextLookupStrategy =
Constraint.isNotNull(strategy, "StateDataContext creation strategy cannot be null");
}
-
/** {@inheritDoc} */
@Override
- protected void doInitialize() throws ComponentInitializationException {
- super.doInitialize();
-
- if (stateDataLookupStrategy == null) {
- throw new ComponentInitializationException("StateDataLookupStrategy cannot be null");
- }
- }
-
- /**
- * Sets the lookup strategy for obtaining the {@link StateData} of the state token.
- *
- * @param strategy lookup strategy
- */
- public void setStateDataLookupStrategy(@Nonnull final Function<ProfileRequestContext,StateData> strategy) {
- checkSetterPreconditions();
-
- stateDataLookupStrategy = Constraint.isNotNull(strategy, "State data lookup strategy cannot be null");
- }
-
- /** {@inheritDoc} */
- @Override
- protected boolean doPreExecute(final ProfileRequestContext profileRequestContext) {
+ protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
if (!super.doPreExecute(profileRequestContext)) {
return false;
}
@@ -132,7 +99,7 @@ public class CreateAuthenticationStateData extends AbstractApplicationAction {
return false;
}
- stateDataContext = stateDataContextCreationStrategy.apply(profileRequestContext);
+ stateDataContext = stateDataContextLookupStrategy.apply(profileRequestContext);
if (stateDataContext == null) {
log.error("{} Error creating or locating StateDataContext", getLogPrefix());
@@ -148,45 +115,34 @@ public class CreateAuthenticationStateData extends AbstractApplicationAction {
return false;
}
+ // If disabled, return false and ignore this action
+ if (!profileConfiguration.isCheckAddress(profileRequestContext)) {
+ log.trace("{} Client address support disabled",getLogPrefix());
+ return false;
+ }
+
return true;
}
-
+
/** {@inheritDoc} */
@Override
- protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
+ protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
- // Before we create new state data, pull out the target URL if either in existing state or from the Agent input
- byte[] target = input.getmember(SPConstants.TARGET).unsafe_string();
- if (target == null) {
- final StateData oldStateData = stateDataContext.getStateData();
- if (oldStateData != null) {
- target = oldStateData.getRawResource();
- }
- }
-
- final StateData stateData = stateDataLookupStrategy.apply(profileRequestContext);
-
+ final StateData stateData = stateDataContext.getStateData();
if (stateData == null) {
- log.error("{} Error creating StateData", getLogPrefix());
+ log.debug("{} State Data was not found", getLogPrefix());
ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
return;
}
-
- // Now add target to state
- stateData.setRawResource(target);
-
- // Now add client address if enabled
- if (profileConfiguration.isCheckAddress(profileRequestContext)) {
- stateData.setClientAddress(
- input.getmember(RemotedHttpServletRequest.STRUCTURE_NAME)
- .getmember(RemotedHttpServletRequest.REMOTE_ADDR)
- .string());
- }
+ final var addr = input.getmember(RemotedHttpServletRequest.STRUCTURE_NAME)
+ .getmember(RemotedHttpServletRequest.REMOTE_ADDR)
+ .string();
+ stateData.setClientAddress(addr);
- stateDataContext.setStateData(stateData);
- log.debug("{} Created authentication state data for preservation '{}'", getLogPrefix(), stateData);
+ log.debug("{} Stored client address '{}' in state data", getLogPrefix(), addr);
}
+
}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddClientIDHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddClientIDHandler.java
index 87d21e9..172ec36 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddClientIDHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddClientIDHandler.java
@@ -23,6 +23,7 @@ import org.slf4j.Logger;
import com.nimbusds.oauth2.sdk.id.ClientID;
import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.primitive.StringSupport;
/**
* A message handler that populates the client_id parameter into the logout request.
@@ -42,9 +43,10 @@ public class AddClientIDHandler extends AbstractLogoutRequestParameterValueMessa
protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
final String clientId = getParameterValue(messageContext);
- if (clientId != null) {
- getLogoutRequest().setClientID(new ClientID(clientId));
- log.trace("{}: Set client_id to '{}'", getLogPrefix(), clientId);
- }
+ if (StringSupport.trimOrNull(clientId) == null) {
+ return;
+ }
+ getLogoutRequest().setClientID(new ClientID(clientId));
+ log.trace("{}: Set client_id to '{}'", getLogPrefix(), clientId);
}
}
\ No newline at end of file
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddIDTokenHintHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddIDTokenHintHandler.java
index 44be868..3b16477 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddIDTokenHintHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddIDTokenHintHandler.java
@@ -14,18 +14,22 @@
package net.shibboleth.sp.oidc.profile.impl;
+import java.text.ParseException;
+
import javax.annotation.Nonnull;
import org.opensaml.messaging.context.MessageContext;
import org.opensaml.messaging.handler.MessageHandlerException;
import org.slf4j.Logger;
+import com.nimbusds.jwt.EncryptedJWT;
import com.nimbusds.jwt.JWT;
+import com.nimbusds.jwt.JWTClaimsSet;
import net.shibboleth.shared.primitive.LoggerFactory;
/**
- * A message handler that populates the login_hint parameter into the logout request.
+ * A message handler that populates the id_token_hint parameter into the logout request.
*/
public class AddIDTokenHintHandler extends AbstractLogoutRequestParameterValueMessageHandler<JWT> {
@@ -42,11 +46,46 @@ public class AddIDTokenHintHandler extends AbstractLogoutRequestParameterValueMe
protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
final JWT idTokenHint = getParameterValue(messageContext);
+ if (idTokenHint == null) {
+ return;
+ }
+ if (idTokenHint instanceof EncryptedJWT) {
+ log.trace("{}: ID Token is still encrypted, possibly for the wrong target, this maybe ignored by "
+ + "the OP", getLogPrefix());
+ }
getLogoutRequest().setIdTokenHint(idTokenHint);
- log.trace("{}: Set id_token_hint to '{}'", getLogPrefix(), idTokenHint);
+ if (log.isTraceEnabled()) {
+ log.trace("{}: Set id_token_hint for subject '{}'", getLogPrefix(),
+ getSubjectOrDefault(idTokenHint,"not-available"));
+ }
}
+ /**
+ * Get the subject from the id_token, else return the default value.
+ *
+ * @param idToken the id_token to extract the subject from
+ * @param defaultSubject the default subject to return if the subject can not be extracted
+ *
+ * @return the subject, either from the id_token or the default value
+ */
+ private String getSubjectOrDefault(final JWT idToken, final String defaultSubject) {
+
+ if (idToken instanceof EncryptedJWT) {
+ return defaultSubject;
+ }
+
+ try {
+ final JWTClaimsSet claims = idToken.getJWTClaimsSet();
+ if (claims != null) {
+ return claims.getSubject() != null ? claims.getSubject() : defaultSubject;
+ }
+ } catch (final ParseException e) {
+ // Ignore
+ }
+ return defaultSubject;
+
+ }
}
\ No newline at end of file
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddLoginHintHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddLogoutHintHandler.java
similarity index 66%
rename from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddLoginHintHandler.java
rename to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddLogoutHintHandler.java
index 49543e3..c20e4f7 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddLoginHintHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddLogoutHintHandler.java
@@ -21,17 +21,18 @@ import org.opensaml.messaging.handler.MessageHandlerException;
import org.slf4j.Logger;
import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.primitive.StringSupport;
/**
- * A message handler that populates the login_hint parameter into the logout request.
+ * A message handler that populates the logout_hint parameter into the logout request.
*/
-public class AddLoginHintHandler extends AbstractLogoutRequestParameterValueMessageHandler<String> {
+public class AddLogoutHintHandler extends AbstractLogoutRequestParameterValueMessageHandler<String> {
/** Logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(AddLoginHintHandler.class);
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddLogoutHintHandler.class);
/** Constructor.*/
- public AddLoginHintHandler() {
+ public AddLogoutHintHandler() {
super(String.class);
}
@@ -39,9 +40,12 @@ public class AddLoginHintHandler extends AbstractLogoutRequestParameterValueMess
@Override
protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
- final String loginHint = getParameterValue(messageContext);
- getLogoutRequest().setLoginHint(loginHint);
- log.trace("{}: Set login_hint to '{}'", getLogPrefix(), loginHint);
+ final String logoutHint = getParameterValue(messageContext);
+ if (StringSupport.trimOrNull(logoutHint) == null) {
+ return;
+ }
+ getLogoutRequest().setLogoutHint(logoutHint);
+ log.trace("{}: Set logout_hint to '{}'", getLogPrefix(), logoutHint);
}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddPostLogoutRedirectURIHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddPostLogoutRedirectURIHandler.java
index b560b0a..aaf5e0e 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddPostLogoutRedirectURIHandler.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddPostLogoutRedirectURIHandler.java
@@ -42,6 +42,9 @@ public class AddPostLogoutRedirectURIHandler extends AbstractLogoutRequestParame
protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
final URI postRedirectUri = getParameterValue(messageContext);
+ if (postRedirectUri == null) {
+ return;
+ }
getLogoutRequest().setPostLogoutRedirectURI(postRedirectUri);
log.trace("{}: Set post_logout_redirect_uri to '{}'", getLogPrefix(), postRedirectUri);
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/CreateAuthenticationStateData.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/CreateStateData.java
similarity index 80%
rename from sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/CreateAuthenticationStateData.java
rename to sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/CreateStateData.java
index a560775..7715f1b 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/CreateAuthenticationStateData.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/CreateStateData.java
@@ -24,9 +24,6 @@ import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
import org.slf4j.Logger;
-import net.shibboleth.idp.profile.IdPEventIds;
-import net.shibboleth.oidc.profile.config.OIDCSSORelyingPartyConfiguration;
-import net.shibboleth.profile.context.RelyingPartyContext;
import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
import net.shibboleth.shared.component.ComponentInitializationException;
@@ -34,7 +31,6 @@ import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.primitive.LoggerFactory;
import net.shibboleth.sp.context.StateDataContext;
import net.shibboleth.sp.ddf.DDF;
-import net.shibboleth.sp.messaging.RemotedHttpServletRequest;
import net.shibboleth.sp.profile.AbstractApplicationAction;
import net.shibboleth.sp.profile.SPConstants;
import net.shibboleth.sp.state.StateData;
@@ -49,10 +45,10 @@ import net.shibboleth.sp.state.StateData;
*
* @event {@link EventIds#INVALID_PROFILE_CTX}
*/
-public class CreateAuthenticationStateData extends AbstractApplicationAction {
+public class CreateStateData extends AbstractApplicationAction {
/** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(CreateAuthenticationStateData.class);
+ @Nonnull private final Logger log = LoggerFactory.getLogger(CreateStateData.class);
/**
* Lookup strategy for the contents of the state token, as stored in a {@link StateData} or subclass thereof.
@@ -63,9 +59,6 @@ public class CreateAuthenticationStateData extends AbstractApplicationAction {
/** Strategy used to locate or create the {@link StateDataContext} to populate. */
@Nonnull private Function<ProfileRequestContext,StateDataContext> stateDataContextCreationStrategy;
- /** Applicable stashed profile configuration. */
- @NonnullBeforeExec private OIDCSSORelyingPartyConfiguration profileConfiguration;
-
/** The stashed state data context.*/
@NonnullBeforeExec private StateDataContext stateDataContext;
@@ -75,7 +68,7 @@ public class CreateAuthenticationStateData extends AbstractApplicationAction {
/**
* Constructor.
*/
- public CreateAuthenticationStateData() {
+ public CreateStateData() {
stateDataContextCreationStrategy = new ChildContextLookup<>(StateDataContext.class, true);
}
@@ -120,18 +113,6 @@ public class CreateAuthenticationStateData extends AbstractApplicationAction {
return false;
}
- final RelyingPartyContext rpCtx = profileRequestContext.getSubcontext(RelyingPartyContext.class);
- if (rpCtx != null && rpCtx.getConfiguration() != null &&
- rpCtx.getProfileConfig() instanceof final OIDCSSORelyingPartyConfiguration
- rpConfig) {
- profileConfiguration = rpConfig;
- }
- if (profileConfiguration == null) {
- log.error("{} Profile configuration not found", getLogPrefix());
- ActionSupport.buildEvent(profileRequestContext, IdPEventIds.INVALID_PROFILE_CONFIG);
- return false;
- }
-
stateDataContext = stateDataContextCreationStrategy.apply(profileRequestContext);
if (stateDataContext == null) {
@@ -175,14 +156,6 @@ public class CreateAuthenticationStateData extends AbstractApplicationAction {
// Now add target to state
stateData.setRawResource(target);
-
- // Now add client address if enabled
- if (profileConfiguration.isCheckAddress(profileRequestContext)) {
- stateData.setClientAddress(
- input.getmember(RemotedHttpServletRequest.STRUCTURE_NAME)
- .getmember(RemotedHttpServletRequest.REMOTE_ADDR)
- .string());
- }
stateDataContext.setStateData(stateData);
log.debug("{} Created authentication state data for preservation '{}'", getLogPrefix(), stateData);
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 55ca76d..01f6e12 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
@@ -28,10 +28,8 @@ import org.slf4j.Logger;
import net.shibboleth.idp.profile.AbstractProfileAction;
import net.shibboleth.idp.profile.IdPEventIds;
-import net.shibboleth.oidc.profile.config.OIDCAuthenticationRelyingPartyProfileConfiguration;
import net.shibboleth.oidc.profile.context.OAuth2ClientContext;
import net.shibboleth.oidc.profile.messaging.context.OIDCPeerEntityContext;
-import net.shibboleth.profile.context.RelyingPartyContext;
import net.shibboleth.profile.context.navigate.IssuerLookupFunction;
import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
import net.shibboleth.shared.logic.Constraint;
@@ -42,14 +40,13 @@ import net.shibboleth.sp.profile.AbstractAgentAction;
/**
* An {@link AbstractProfileAction action} that resolves the client identifier and redirect URI for the chosen
- * provider (issuer).
+ * provider (issuer). This is similar to a 'self' context in the same sense.
*
* @event {@link org.opensaml.profile.action.EventIds#PROCEED_EVENT_ID}
* @event {@link IdPEventIds#INVALID_PROFILE_CONFIG}
* @event {@link EventIds#INVALID_PROFILE_CTX}
* @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
public class InitializeOAuth2ClientContext extends AbstractAgentAction {
/** Class logger. */
@@ -65,38 +62,20 @@ public class InitializeOAuth2ClientContext extends AbstractAgentAction {
/** A redirect_uri lookup strategy which can pull out an override redirect_uri from the profile request context.*/
@Nonnull private Function<ProfileRequestContext, URI> redirectUriOverrideLookupStrategy;
- /** Lookup function for relying party context. */
- @Nonnull private Function<ProfileRequestContext,RelyingPartyContext> relyingPartyContextLookupStrategy;
-
/** Strategy used to obtain the request issuer value. */
@Nonnull private Function<ProfileRequestContext,String> issuerLookupStrategy;
- /** Applicable stashed profile configuration. */
- @NonnullBeforeExec private OIDCAuthenticationRelyingPartyProfileConfiguration profileConfiguration;
-
/** Constructor.*/
public InitializeOAuth2ClientContext() {
// Default under OIDCPeerEntityContext in the outbound context (create true).
oauth2ClientContextLookupStrategy = new ChildContextLookup<>(OAuth2ClientContext.class, true).compose(
new ChildContextLookup<>(OIDCPeerEntityContext.class).compose(
new OutboundMessageContextLookup()));
-
- relyingPartyContextLookupStrategy = new ChildContextLookup<>(RelyingPartyContext.class);
+
redirectUriOverrideLookupStrategy = new RedirectUriLookupFunction();
issuerLookupStrategy = new IssuerLookupFunction();
}
- /**
- * Set lookup strategy for relying party context.
- *
- * @param strategy lookup strategy
- */
- public void setRelyingPartyContextLookupStrategy(
- @Nonnull final Function<ProfileRequestContext,RelyingPartyContext> strategy) {
- relyingPartyContextLookupStrategy =
- Constraint.isNotNull(strategy, "RelyingPartyContext lookup strategy cannot be null");
- }
-
/**
* Set the strategy used to locate the issuer value to use.
*
@@ -148,17 +127,6 @@ public class InitializeOAuth2ClientContext extends AbstractAgentAction {
return false;
}
- final RelyingPartyContext rpCtx = relyingPartyContextLookupStrategy.apply(profileRequestContext);
- if (rpCtx != null && rpCtx.getConfiguration() != null &&
- rpCtx.getProfileConfig() instanceof final OIDCAuthenticationRelyingPartyProfileConfiguration rpConfig) {
- profileConfiguration = rpConfig;
- }
- if (profileConfiguration == null) {
- log.error("{} OIDCAuthorizationConfiguration not found", getLogPrefix());
- ActionSupport.buildEvent(profileRequestContext, IdPEventIds.INVALID_PROFILE_CONFIG);
- return false;
- }
-
return true;
}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/InitializeOutboundMessageContext.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/InitializeOutboundMessageContext.java
index 02cec41..2fdbdad 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/InitializeOutboundMessageContext.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/InitializeOutboundMessageContext.java
@@ -138,8 +138,6 @@ public class InitializeOutboundMessageContext extends AbstractProfileAction {
final MessageContext msgCtx = new MessageContext();
profileRequestContext.setOutboundMessageContext(msgCtx);
- //TODO self context for info about RP?
-
final OIDCPeerEntityContext outboundPeerContext = msgCtx.ensureSubcontext(OIDCPeerEntityContext.class);
outboundPeerContext.setIdentifier(peerEntityCtx.getIdentifier());
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/LogoutRequestStateForStorageStrategy.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/LogoutRequestStateForStorageStrategy.java
new file mode 100644
index 0000000..c95086f
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/LogoutRequestStateForStorageStrategy.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.util.function.Function;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
+import net.shibboleth.sp.oidc.profile.LogoutRequestStateData;
+import net.shibboleth.sp.state.StateData;
+
+/**
+ * A {@link Function} that produces {@link StateData} representing logout request state that is required
+ * for validating the logout response (if there is one). This can be stored in a way that can be recovered later
+ * when the response is received.
+ */
+public class LogoutRequestStateForStorageStrategy extends AbstractIdentifiableInitializableComponent
+ implements Function<ProfileRequestContext,LogoutRequestStateData> {
+
+ /** {@inheritDoc} */
+ @Override
+ public LogoutRequestStateData apply(final ProfileRequestContext prc) {
+ return new LogoutRequestStateData();
+ }
+
+
+}
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/PreserveOAuthState.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/PreserveOAuthState.java
new file mode 100644
index 0000000..f240a3f
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/PreserveOAuthState.java
@@ -0,0 +1,68 @@
+/*
+ * 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 org.opensaml.messaging.context.MessageContext;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+
+import com.nimbusds.oauth2.sdk.id.State;
+import com.nimbusds.openid.connect.sdk.claims.ClaimsSet;
+
+import net.shibboleth.oidc.profile.core.OIDCAuthenticationRequest;
+import net.shibboleth.oidc.profile.core.OIDCLogoutRequest;
+import net.shibboleth.oidc.profile.core.StateToken;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.sp.profile.PreserveStateDataAction;
+
+/**
+ * OAuth/OIDC-specific action that processes the state token by setting it as the state value.
+ */
+public class PreserveOAuthState extends PreserveStateDataAction {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(PreserveOAuthState.class);
+
+ /** The 'state' claim name.*/
+ @Nonnull private static final String STATE_CLAIM = "state";
+
+ /** {@inheritDoc} */
+ @Override
+ protected void processToken(@Nonnull final ProfileRequestContext profileRequestContext,
+ @Nonnull @NotEmpty final String token) {
+
+ final MessageContext outbound = profileRequestContext.ensureOutboundMessageContext();
+ if (outbound.getMessage() instanceof final OIDCAuthenticationRequest request) {
+ log.trace("{} Setting OAuth2.0 state in authentication request to to '{}", getLogPrefix(), token);
+ request.setStateToken(new StateToken(token, null));
+
+ // Add to Request Object if exists
+ final ClaimsSet claims = request.getRequestObjectClaimsSet();
+ if (claims != null) {
+ log.trace("{} Adding OAuth2.0 state to JWT RequestObject", getLogPrefix());
+ claims.setClaim(STATE_CLAIM, token);
+ }
+
+ }
+ if (outbound.getMessage() instanceof final OIDCLogoutRequest request) {
+ log.trace("{} Setting OAuth2.0 state in logout request to '{}", getLogPrefix(), token);
+ request.setState(new State(token));
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/sp-oidc-impl/src/test/java/net/shibboleth/sp/oidc/profile/impl/CreateAuthenticationStateDataTest.java b/sp-oidc-impl/src/test/java/net/shibboleth/sp/oidc/profile/impl/CreateAuthenticationStateDataTest.java
index 79714d0..93bbc6e 100644
--- a/sp-oidc-impl/src/test/java/net/shibboleth/sp/oidc/profile/impl/CreateAuthenticationStateDataTest.java
+++ b/sp-oidc-impl/src/test/java/net/shibboleth/sp/oidc/profile/impl/CreateAuthenticationStateDataTest.java
@@ -30,19 +30,18 @@ import net.shibboleth.profile.context.RelyingPartyContext;
import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.sp.context.StateDataContext;
import net.shibboleth.sp.ddf.DDF;
-import net.shibboleth.sp.messaging.RemotedHttpServletRequest;
import net.shibboleth.sp.oidc.profile.AuthenticationRequestStateData;
import net.shibboleth.sp.oidc.testing.TestConstants;
import net.shibboleth.sp.profile.SPConstants;
import net.shibboleth.sp.profile.impl.BaseApplicationActionTest;
/**
- * Tests for {@link CreateAuthenticationStateData}.
+ * Tests for {@link CreateStateData}.
*/
public class CreateAuthenticationStateDataTest extends BaseApplicationActionTest {
/** The action being tested. */
- private CreateAuthenticationStateData action;
+ private CreateStateData action;
/** The RelyingPartyContext to be used in the tests. */
private RelyingPartyContext partyContext;
@@ -65,7 +64,7 @@ public class CreateAuthenticationStateDataTest extends BaseApplicationActionTest
public void beforeMethod() throws ComponentInitializationException {
super.beforeMethod();
- action = new CreateAuthenticationStateData();
+ action = new CreateStateData();
partyContext = prc.ensureSubcontext(RelyingPartyContext.class);
@@ -123,19 +122,6 @@ public class CreateAuthenticationStateDataTest extends BaseApplicationActionTest
ActionTestingSupport.assertProceedEvent(event);
assertNull(authnState.getResource());
}
-
- @Test
- public void testSuccess_CheckAddress() throws ComponentInitializationException {
- input.addmember(RemotedHttpServletRequest.STRUCTURE_NAME).addmember(RemotedHttpServletRequest.REMOTE_ADDR)
- .string("192.168.1.1");
- rpConfig.setCheckAddress(true);
- action.initialize();
-
- final Event event = action.execute(src);
- ActionTestingSupport.assertProceedEvent(event);
- assertEquals(authnState.getResource(), TestConstants.RESOURCE_URL);
- assertEquals(authnState.getClientAddress(), "192.168.1.1");
- }
@Test
public void testSuccess_OldStateHasResource() throws ComponentInitializationException {
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list