[java-plugin-shibd-oidc] 04/06: WiP for logout: Add basic logout request message handlers
Codeberg
noreply at shibboleth.net
Fri Jul 3 13:33:01 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/db84456de822f06ad7a807dd4d703fc1158d6da1
commit db84456de822f06ad7a807dd4d703fc1158d6da1
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Fri Jun 26 17:10:06 2026 +0100
WiP for logout: Add basic logout request message handlers
- Add basic logout request message handlers to build the logout request
- Some of these will need to be moved into commons.
---
...outRequestFromMessageContextLookupFunction.java | 37 ++++
...oviderMetadataLogoutEndpointLookupStrategy.java | 70 +++++++
.../shibboleth/sp/oidc/testing/TestConstants.java | 7 +-
.../idp/flows/sp/consumer/oidc/oidc-beans.xml | 2 +-
.../idp/flows/sp/initiator/oidc/oidc-beans.xml | 17 --
.../idp/flows/sp/initiator/oidc/oidc-flow.xml | 2 +-
.../flows/sp/logout/consumer/oidc/oidc-beans.xml | 2 +-
.../flows/sp/logout/initiator/oidc/oidc-beans.xml | 75 +++++++-
.../flows/sp/logout/initiator/oidc/oidc-flow.xml | 22 ++-
.../shibboleth/idp/flows/sp/oidc-common-beans.xml | 30 ++-
.../net/shibboleth/sp/service/agent/postconfig.xml | 18 +-
.../oidc/flows/OIDCSessionInitiatorFlowTest.java | 20 +-
.../sp/oidc/flows/OIDCTokenConsumerFlowTest.java | 64 +++----
...DCTokenConsumerFlowUsingStorageServiceTest.java | 6 +-
.../resources/metadata/openid-configuration.json | 4 +-
...tLogoutRequestParameterValueMessageHandler.java | 204 +++++++++++++++++++++
.../sp/oidc/profile/impl/AddClientIDHandler.java | 50 +++++
.../oidc/profile/impl/AddIDTokenHintHandler.java | 52 ++++++
.../sp/oidc/profile/impl/AddLoginHintHandler.java | 50 +++++
.../impl/AddPostLogoutRedirectURIHandler.java | 52 ++++++
.../sp/oidc/profile/impl/AddUILocalesHandler.java | 68 +++++++
.../oidc/profile/impl/InitializeLogoutRequest.java | 151 +++++++++++++++
.../impl/InitializeOutboundMessageContext.java | 2 +-
.../InitializeRelyingPartyContextFromOIDCPeer.java | 2 +
.../impl/ProcessLogoutInitiatorRequest.java | 2 +
25 files changed, 924 insertions(+), 85 deletions(-)
diff --git a/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/messaging/context/navigate/LogoutRequestFromMessageContextLookupFunction.java b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/messaging/context/navigate/LogoutRequestFromMessageContextLookupFunction.java
new file mode 100644
index 0000000..4e64221
--- /dev/null
+++ b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/messaging/context/navigate/LogoutRequestFromMessageContextLookupFunction.java
@@ -0,0 +1,37 @@
+/*
+ * 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.context.navigate;
+
+import java.util.function.Function;
+
+import org.opensaml.messaging.context.MessageContext;
+
+import net.shibboleth.oidc.profile.core.OIDCLogoutRequest;
+
+/**
+ * A function that returns the {@link OIDCLogoutRequest} from the given {@link MessageContext}.
+ */
+public class LogoutRequestFromMessageContextLookupFunction implements Function<MessageContext, OIDCLogoutRequest>{
+
+ /** {@inheritDoc} */
+ @Override
+ public OIDCLogoutRequest apply(final MessageContext msgContext) {
+ if (msgContext.getMessage() instanceof final OIDCLogoutRequest request) {
+ return request;
+ }
+ return null;
+ }
+
+}
diff --git a/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/messaging/context/navigate/ProviderMetadataLogoutEndpointLookupStrategy.java b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/messaging/context/navigate/ProviderMetadataLogoutEndpointLookupStrategy.java
new file mode 100644
index 0000000..70572e5
--- /dev/null
+++ b/sp-oidc-api/src/main/java/net/shibboleth/sp/oidc/messaging/context/navigate/ProviderMetadataLogoutEndpointLookupStrategy.java
@@ -0,0 +1,70 @@
+/*
+ * 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.context.navigate;
+
+import java.net.URI;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
+
+import net.shibboleth.oidc.metadata.context.OIDCProviderMetadataContext;
+import net.shibboleth.shared.annotation.ParameterName;
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.logic.Constraint;
+
+/**
+ * A strategy to locate the end_session_endpoint (logout) of the OP from it's discovery metadata.
+ */
+public class ProviderMetadataLogoutEndpointLookupStrategy implements Function<ProfileRequestContext, URI> {
+
+ /** Lookup strategy to locate the OpenID Provider metadata to use.*/
+ @NonnullAfterInit
+ private final Function<ProfileRequestContext, OIDCProviderMetadataContext> providerMetadataLookupStrategy;
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param strategy strategy to locate the provider metadata context.
+ */
+ public ProviderMetadataLogoutEndpointLookupStrategy(
+ @ParameterName(name="providerMetadataLookupStrategy") @Nonnull final
+ Function<ProfileRequestContext, OIDCProviderMetadataContext> strategy) {
+ providerMetadataLookupStrategy =
+ Constraint.isNotNull(strategy, "ProviderMetadataLookupStrategy can not be null");
+ }
+
+
+ /** {@inheritDoc} */
+ @Override
+ public URI apply(final ProfileRequestContext prc) {
+
+ final OIDCProviderMetadataContext providerMetadataContext = providerMetadataLookupStrategy.apply(prc);
+ if (providerMetadataContext == null) {
+ return null;
+ }
+
+ final OIDCProviderMetadata metadata = providerMetadataContext.getProviderInformation();
+ if (metadata == null) {
+ return null;
+ }
+ return metadata.getEndSessionEndpointURI();
+ }
+
+}
diff --git a/sp-oidc-api/src/test/java/net/shibboleth/sp/oidc/testing/TestConstants.java b/sp-oidc-api/src/test/java/net/shibboleth/sp/oidc/testing/TestConstants.java
index 10849a3..1ec7ffb 100644
--- a/sp-oidc-api/src/test/java/net/shibboleth/sp/oidc/testing/TestConstants.java
+++ b/sp-oidc-api/src/test/java/net/shibboleth/sp/oidc/testing/TestConstants.java
@@ -46,8 +46,11 @@ public final class TestConstants {
/** State token string used in cookie names. */
public static final String STATE_TOKEN = "1761316967710_1622a5c726da8f7b36e24f19eed82aea";
- /** Application ID. */
- public static final String APPLICATION_ID = "test-oidc-application-with-ro";
+ /** Application ID for an application that uses the request object in the request. */
+ public static final String APPLICATION_ID_REQUEST_OBJECT = "test-oidc-application-with-ro";
+
+ /** Default Application ID that supports all default profiles and no special configuration. */
+ public static final String APPLICATION_ID = "test-oidc-application-with-default-profile";
/** Application ID used when private_key_jwt has been configured.*/
public static final String APPLICATION_ID_PRIVATE_KEY_JWT = "test-oidc-application-with-ro-private-key-jwt";
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 758dbac..a3be0e8 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
@@ -57,7 +57,7 @@
<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 2ae3c46..68f07e2 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
@@ -29,26 +29,9 @@
p:relyingPartyLookupStrategy-ref="shibboleth.RelyingPartyIdLookup.Simple">
</bean>
- <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" />
-
<!-- <bean id="InitializeOutboundMessageContext" class="net.shibboleth.idp.saml.profile.impl.InitializeOutboundMessageContext"
scope="prototype" p:selfIdentityLookupStrategy-ref="shibboleth.IssuerLookup.Simple" /> -->
- <!-- TODO, self context -->
- <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" />
-
<bean id="InitializeAuthorizationRequest"
class="net.shibboleth.sp.oidc.profile.impl.InitializeAuthorizationRequest" 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 297154b..a8f3e86 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
@@ -5,7 +5,7 @@
<action-state id="OIDCSessionInitiator">
<evaluate expression="ValidateSessionInitiatorRequest" />
- <evaluate expression="PrepareInboundMessageContext" /> <!-- needs session and logout support -->
+ <evaluate expression="PrepareInboundMessageContext" />
<evaluate expression="ProviderMetadataLookup" />
<evaluate expression="InitializeRelyingPartyContextFromOIDCPeer" />
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 c0154e6..7b37f0d 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
@@ -7,7 +7,7 @@
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
default-init-method="initialize" default-destroy-method="destroy">
- <util:constant id="shiibboleth.sp.ProfileId"
+ <util:constant id="shibboleth.sp.oidc.ProfileId"
static-field="net.shibboleth.saml.saml2.profile.config.SingleLogoutProfileConfiguration.PROFILE_ID" />
<util:constant id="shibboleth.EndpointType"
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 b4f14c4..937c0b4 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
@@ -7,14 +7,20 @@
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
default-init-method="initialize" default-destroy-method="destroy">
- <util:constant id="shiibboleth.sp.ProfileId"
- static-field="net.shibboleth.saml.saml2.profile.config.SingleLogoutProfileConfiguration.PROFILE_ID" />
+ <util:constant id="shibboleth.sp.oidc.ProfileId"
+ static-field="net.shibboleth.oidc.profile.config.OIDCLogoutProfileConfiguration.PROFILE_ID" />
<import resource="classpath:/META-INF/net/shibboleth/idp/flows/sp/oidc-common-beans.xml" />
<bean id="ProcessLogoutInitiatorRequest"
class="net.shibboleth.sp.oidc.profile.impl.ProcessLogoutInitiatorRequest" scope="prototype"
p:dataSealer-ref="#{'%{sp.dataSealer:shibboleth.DataSealer}'.trim()}"/>
+
+ <!-- Prepare the OIDC Peer Entity with the relying party ID (the OP identifier) -->
+ <bean id="PrepareInboundMessageContext"
+ 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" />
@@ -28,4 +34,69 @@
</property>
</bean> -->
+ <bean id="InitializeLogoutRequest" class="net.shibboleth.sp.oidc.profile.impl.InitializeLogoutRequest">
+ <property name="logoutEndpointLookupStrategy">
+ <bean id="logoutEndpointLookupStrategy"
+ class="net.shibboleth.sp.oidc.messaging.context.navigate.ProviderMetadataLogoutEndpointLookupStrategy"
+ c:providerMetadataLookupStrategy-ref="shibboleth.ChildLookup.OIDCProviderMetadataContextFromOutbound"/>
+ </property>
+ </bean>
+
+ <!-- Abstract LogoutRequestHandler bean to establish strategies -->
+ <bean id="LogoutRequestHandler" abstract="true"
+ p:providerMetadataLookupStrategy-ref="shibboleth.ChildLookup.OIDCProviderMetadataContextFromPeerContext">
+ <property name="logoutRequestLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.messaging.context.navigate.LogoutRequestFromMessageContextLookupFunction"/>
+ </property>
+ </bean>
+
+ <bean id="BuildLogoutRequest" parent="WebFlowOutboundMessageHandlerAdaptor" scope="prototype">
+ <constructor-arg>
+ <bean class="org.opensaml.messaging.handler.impl.BasicMessageHandlerChain">
+ <property name="handlers">
+ <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"
+ scope="prototype" />
+ </property> -->
+ </bean>
+ <bean id="AddLoginHint" scope="prototype" parent="LogoutRequestHandler"
+ class="net.shibboleth.sp.oidc.profile.impl.AddLoginHintHandler">
+ <!-- <property name="parameterValueLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.config.navigate.ResponseTypeLookupStrategy"
+ scope="prototype" />
+ </property> -->
+ </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> -->
+ </bean>
+ <bean id="AddPostLogoutRedirectURI" scope="prototype" parent="LogoutRequestHandler"
+ class="net.shibboleth.sp.oidc.profile.impl.AddPostLogoutRedirectURIHandler">
+ <!-- <property name="parameterValueLookupStrategy">
+ <bean class="net.shibboleth.sp.oidc.profile.config.navigate.ResponseTypeLookupStrategy"
+ scope="prototype" />
+ </property> -->
+ </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"
+ scope="prototype" />
+ </property> -->
+ </bean>
+ </list>
+ </property>
+ </bean>
+ </constructor-arg>
+ <property name="errorEvent">
+ <util:constant static-field="org.opensaml.profile.action.EventIds.INVALID_MESSAGE" />
+ </property>
+ </bean>
+
</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 fb24083..017bbcb 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
@@ -5,25 +5,27 @@
<action-state id="SAML2LogoutInitiator">
<evaluate expression="ProcessLogoutInitiatorRequest" />
- <!-- <evaluate expression="PrepareInboundMessageContext" />
- <evaluate expression="SAMLProtocolAndRole" />
- <evaluate expression="SAMLMetadataLookup" />
+ <evaluate expression="PrepareInboundMessageContext" />
+ <evaluate expression="ProviderMetadataLookup" />
- <evaluate expression="InitializeRelyingPartyContextFromSAMLPeer" />
+ <evaluate expression="InitializeRelyingPartyContextFromOIDCPeer" /> <!-- Seems a bit redundant in logout as ProcessLogoutInitiatorRequest has already created it, although not quite in the right state -->
<evaluate expression="SelectRelyingPartyConfiguration" />
<evaluate expression="SelectProfileConfiguration" />
- <evaluate expression="InitializeOutboundMessageContext" />
- <evaluate expression="InitializeMessageChannelSecurityContext" />
+
+ <evaluate expression="InitializeOutboundMessageContext" />
+ <!-- <evaluate expression="InitializeOAuth2ClientContext" />-->
+ <evaluate expression="InitializeLogoutRequest" />
+ <!-- <evaluate expression="InitializeMessageChannelSecurityContext" />
<evaluate expression="PopulateBindingAndEndpointContexts" />
<evaluate expression="PopulateRequestSignatureSigningParameters" />
- <evaluate expression="PopulateEncryptionParameters" />
+ <evaluate expression="PopulateEncryptionParameters" />-->
- <evaluate expression="AddLogoutRequest" />
- <evaluate expression="EncryptNameIDs" />
+ <evaluate expression="BuildLogoutRequest" />
+ <!-- <evaluate expression="EncryptNameIDs" /> -->
- <evaluate expression="HandleOutboundMessage" />
+<!-- <evaluate expression="HandleOutboundMessage" />
<evaluate expression="PreserveRelayState" />
<evaluate expression="EncodeMessage" /> -->
<evaluate expression="'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 0894f60..5125d99 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
@@ -79,6 +79,10 @@
class="org.opensaml.messaging.context.navigate.ChildContextLookup"
c:type="#{ T(net.shibboleth.sp.context.StateDataContext) }" />
+ <bean id="shibboleth.ChildLookup.LogoutContext"
+ class="org.opensaml.messaging.context.navigate.ChildContextLookup"
+ c:type="#{ T(net.shibboleth.sp.oidc.context.OIDCLogoutContext) }" />
+
<bean id="shibboleth.ChildLookupOrCreate.StateDataContext"
class="org.opensaml.messaging.context.navigate.ChildContextLookup"
c:type="#{ T(net.shibboleth.sp.context.StateDataContext) }"
@@ -223,19 +227,39 @@
</constructor-arg>
</bean>
-
<!-- Common Actions -->
<bean id="ProviderMetadataLookup" parent="WebFlowInboundMessageHandlerAdaptor" scope="prototype">
<constructor-arg name="messageHandler">
<bean class="net.shibboleth.sp.oidc.metadata.impl.OIDCProviderMetadataLookupHandler"
- scope="prototype">
+ scope="prototype"
+ p:contextClassLookupStrategy-ref="shibboleth.ChildLookup.OIDCPeerEntityContext"> <!-- Add under the PeerEntityContext -->
<property name="ProviderMetadataResolverLookupStrategy">
<bean class="net.shibboleth.sp.oidc.profile.impl.ApplicationMetadataResolverLookupFunction" />
</property>
</bean>
</constructor-arg>
- </bean>
+ </bean>
+
+ <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" />
+
+ <!-- TODO, self context -->
+ <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/META-INF/net/shibboleth/sp/service/agent/postconfig.xml b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/sp/service/agent/postconfig.xml
index eeb0406..5590049 100644
--- a/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/sp/service/agent/postconfig.xml
+++ b/sp-oidc-conf-impl/src/main/resources/META-INF/net/shibboleth/sp/service/agent/postconfig.xml
@@ -29,7 +29,7 @@
<property name="defaultProfileConfigurations">
<list>
<ref bean="OIDC.SSO" />
- <!-- <ref bean="OIDC.Logout" /> -->
+ <ref bean="OIDC.Logout"/>
</list>
</property>
<property name="metadataDrivenDefaultProfileConfigurations">
@@ -107,6 +107,22 @@
p:checkAddressPredicate="%{sp.oidc.checkAddress:false}">
</bean>
+ <bean id="OIDC.Logout" parent="AbstractOIDCProfile" lazy-init="true"
+ class="net.shibboleth.oidc.profile.config.impl.DefaultOIDCLogoutConfiguration"/>
+
+ <!-- TODO, Which of these profile options do we need? -->
+ <!--
+ p:issuer-ref="shibboleth.oidc.issuer"
+ p:logoutHintMatchingStrategy-ref="%{idp.oidc.logout.logoutHintMatchingStrategy:DefaultLogoutHintMatchingPredicate}"
+ p:securityConfiguration-ref="%{idp.security.oidc.logout.config:shibboleth.oidc.logout.DefaultSecurityConfiguration}"
+ p:preferFrontChannel="%{idp.oidc.logout.preferFrontChannel:true}"
+ p:frontChannelSuccess="%{idp.oidc.logout.frontChannelSuccess:false}"
+ p:revokeTokens="%{idp.oidc.logout.revokeTokens:true}"
+ p:requireIdTokenHint="%{idp.oidc.logout.requireIdTokenHint:true}"
+ p:encryptionOptional="%{idp.oidc.logout.encryptionOptional:true}"
+ p:ignoreInvalidPostLogoutRedirectUri="%{idp.oidc.logout.ignoreInvalidPostLogoutRedirectUri:false}" -->
+
+
<util:constant id="OIDC.SSO.FEATURE_ESSENTIAL_ACR_REQUEST"
static-field="net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration.FEATURE_ESSENTIAL_ACR_REQUEST"/>
diff --git a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCSessionInitiatorFlowTest.java b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCSessionInitiatorFlowTest.java
index 96ce49e..6d2f2ca 100644
--- a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCSessionInitiatorFlowTest.java
+++ b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCSessionInitiatorFlowTest.java
@@ -161,7 +161,7 @@ public class OIDCSessionInitiatorFlowTest extends AbstractSPFlowTest {
input.addmember(RemotedHttpServletRequest.STRUCTURE_NAME).structure();
input.addmember(InitiatorConstants.RESPONSE_URL).string(RESPONSE_URL);
input.addmember(SPConstants.TARGET).unsafe_string(RESOURCE_URL);
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, FLOW_ID);
@@ -234,7 +234,7 @@ public class OIDCSessionInitiatorFlowTest extends AbstractSPFlowTest {
input.addmember(InitiatorConstants.RESPONSE_URL).string(RESPONSE_URL);
input.addmember(SPConstants.TARGET).unsafe_string(RESOURCE_URL);
input.addmember(SPConstants.STATE).string("state");
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, FLOW_ID);
@@ -257,7 +257,7 @@ public class OIDCSessionInitiatorFlowTest extends AbstractSPFlowTest {
input.addmember(InitiatorConstants.RESPONSE_URL).string(RESPONSE_URL);
input.addmember(SPConstants.TARGET).unsafe_string(RESOURCE_URL);
input.addmember(OIDCInitiatorConstants.FORCE_AUTHN).integer(1);
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, FLOW_ID);
@@ -282,7 +282,7 @@ public class OIDCSessionInitiatorFlowTest extends AbstractSPFlowTest {
input.addmember(InitiatorConstants.RESPONSE_URL).string(RESPONSE_URL);
input.addmember(SPConstants.TARGET).unsafe_string(RESOURCE_URL);
input.addmember(OIDCInitiatorConstants.MAX_AGE).longinteger(60l);
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, FLOW_ID);
@@ -306,7 +306,7 @@ public class OIDCSessionInitiatorFlowTest extends AbstractSPFlowTest {
input.addmember(InitiatorConstants.RESPONSE_URL).string(RESPONSE_URL);
input.addmember(SPConstants.TARGET).unsafe_string(RESOURCE_URL);
input.addmember(OIDCInitiatorConstants.PROMPT).string("none");
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, FLOW_ID);
@@ -333,7 +333,7 @@ public class OIDCSessionInitiatorFlowTest extends AbstractSPFlowTest {
aclist.add(new DDF(null).string("loa1"));
aclist.add(new DDF(null).string("loa2"));
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, FLOW_ID);
@@ -402,7 +402,7 @@ public class OIDCSessionInitiatorFlowTest extends AbstractSPFlowTest {
resourceList.add(new DDF(null).string("https://cal.example.com"));
resourceList.add(new DDF(null).string("https://mail.example.com"));
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, FLOW_ID);
@@ -428,7 +428,7 @@ public class OIDCSessionInitiatorFlowTest extends AbstractSPFlowTest {
input.addmember(InitiatorConstants.RESPONSE_URL).string(RESPONSE_URL);
input.addmember(SPConstants.TARGET).unsafe_string(RESOURCE_URL);
input.addmember(OIDCInitiatorConstants.SCOPE).string("email");
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, FLOW_ID);
@@ -452,7 +452,7 @@ public class OIDCSessionInitiatorFlowTest extends AbstractSPFlowTest {
input.addmember(InitiatorConstants.RESPONSE_URL).string(RESPONSE_URL);
input.addmember(SPConstants.TARGET).unsafe_string(RESOURCE_URL);
input.addmember(OIDCInitiatorConstants.UI_LOCALES).string("fr-CA fr en");
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, FLOW_ID);
@@ -477,7 +477,7 @@ public class OIDCSessionInitiatorFlowTest extends AbstractSPFlowTest {
input.addmember(InitiatorConstants.RESPONSE_URL).string(RESPONSE_URL);
input.addmember(SPConstants.TARGET).unsafe_string(RESOURCE_URL);
input.addmember(OIDCInitiatorConstants.DISPLAY).string("page");
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, FLOW_ID);
diff --git a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java
index a06afe6..d6bb66f 100644
--- a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java
+++ b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java
@@ -99,10 +99,10 @@ public class OIDCTokenConsumerFlowTest extends AbstractOIDCTokenConsumerFlowTest
// Add cookies
input.addmember("http.headers.Cookie").unsafe_string(TestHelper.buildCookieHeader(
TestConstants.STATE_TOKEN,
- TestConstants.APPLICATION_ID,
+ TestConstants.APPLICATION_ID_REQUEST_OBJECT,
TestHelper.buildAuthenticationState(null, false, null), true));
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, TestConstants.FLOW_ID);
@@ -204,10 +204,10 @@ public class OIDCTokenConsumerFlowTest extends AbstractOIDCTokenConsumerFlowTest
// Add cookies
input.addmember("http.headers.Cookie").unsafe_string(TestHelper.buildCookieHeader(
TestConstants.STATE_TOKEN,
- TestConstants.APPLICATION_ID,
+ TestConstants.APPLICATION_ID_REQUEST_OBJECT,
TestHelper.buildAuthenticationState(Duration.ofMinutes(1), true, null), true));
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, TestConstants.FLOW_ID);
@@ -238,10 +238,10 @@ public class OIDCTokenConsumerFlowTest extends AbstractOIDCTokenConsumerFlowTest
// Add cookies
input.addmember("http.headers.Cookie").unsafe_string(TestHelper.buildCookieHeader(
TestConstants.STATE_TOKEN,
- TestConstants.APPLICATION_ID,
+ TestConstants.APPLICATION_ID_REQUEST_OBJECT,
TestHelper.buildAuthenticationState(Duration.ofMinutes(1), true, null), true));
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, TestConstants.FLOW_ID);
@@ -271,10 +271,10 @@ public class OIDCTokenConsumerFlowTest extends AbstractOIDCTokenConsumerFlowTest
// Add cookies
input.addmember("http.headers.Cookie").unsafe_string(TestHelper.buildCookieHeader(
TestConstants.STATE_TOKEN,
- TestConstants.APPLICATION_ID,
+ TestConstants.APPLICATION_ID_REQUEST_OBJECT,
TestHelper.buildAuthenticationState(null, false, null), true));
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, TestConstants.FLOW_ID);
@@ -305,10 +305,10 @@ public class OIDCTokenConsumerFlowTest extends AbstractOIDCTokenConsumerFlowTest
// Add cookies
input.addmember("http.headers.Cookie").unsafe_string(TestHelper.buildCookieHeader(
TestConstants.STATE_TOKEN,
- TestConstants.APPLICATION_ID,
+ TestConstants.APPLICATION_ID_REQUEST_OBJECT,
TestHelper.buildAuthenticationState(null, false, null), true));
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, TestConstants.FLOW_ID);
@@ -340,10 +340,10 @@ public class OIDCTokenConsumerFlowTest extends AbstractOIDCTokenConsumerFlowTest
// Add cookies
input.addmember("http.headers.Cookie").unsafe_string(TestHelper.buildCookieHeader(
TestConstants.STATE_TOKEN,
- TestConstants.APPLICATION_ID,
+ TestConstants.APPLICATION_ID_REQUEST_OBJECT,
TestHelper.buildAuthenticationState(null, false, CollectionSupport.listOf("loa1")), true));
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, TestConstants.FLOW_ID);
@@ -378,10 +378,10 @@ public class OIDCTokenConsumerFlowTest extends AbstractOIDCTokenConsumerFlowTest
// Add cookies
input.addmember("http.headers.Cookie").unsafe_string(TestHelper.buildCookieHeader(
TestConstants.STATE_TOKEN,
- TestConstants.APPLICATION_ID,
+ TestConstants.APPLICATION_ID_REQUEST_OBJECT,
TestHelper.buildAuthenticationState(null, false, CollectionSupport.listOf("loa1")), true));
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, TestConstants.FLOW_ID);
@@ -413,10 +413,10 @@ public class OIDCTokenConsumerFlowTest extends AbstractOIDCTokenConsumerFlowTest
// Add cookies
input.addmember("http.headers.Cookie").unsafe_string(TestHelper.buildCookieHeader(
TestConstants.STATE_TOKEN,
- TestConstants.APPLICATION_ID,
+ TestConstants.APPLICATION_ID_REQUEST_OBJECT,
TestHelper.buildAuthenticationState(null, false, null), true));
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, TestConstants.FLOW_ID);
@@ -446,10 +446,10 @@ public class OIDCTokenConsumerFlowTest extends AbstractOIDCTokenConsumerFlowTest
// Add cookies
input.addmember("http.headers.Cookie").unsafe_string(TestHelper.buildCookieHeader(
TestConstants.STATE_TOKEN,
- TestConstants.APPLICATION_ID,
+ TestConstants.APPLICATION_ID_REQUEST_OBJECT,
TestHelper.buildAuthenticationState(null, false, null), true));
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, TestConstants.FLOW_ID);
@@ -480,10 +480,10 @@ public class OIDCTokenConsumerFlowTest extends AbstractOIDCTokenConsumerFlowTest
// Add cookies
input.addmember("http.headers.Cookie").unsafe_string(TestHelper.buildCookieHeader(
TestConstants.STATE_TOKEN,
- TestConstants.APPLICATION_ID,
+ TestConstants.APPLICATION_ID_REQUEST_OBJECT,
TestHelper.buildAuthenticationState(null, false, null), true));
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, TestConstants.FLOW_ID);
@@ -511,10 +511,10 @@ public class OIDCTokenConsumerFlowTest extends AbstractOIDCTokenConsumerFlowTest
// Add cookies
input.addmember("http.headers.Cookie").unsafe_string(TestHelper.buildCookieHeader(
TestConstants.STATE_TOKEN,
- TestConstants.APPLICATION_ID,
+ TestConstants.APPLICATION_ID_REQUEST_OBJECT,
TestHelper.buildAuthenticationState(null, false, null), true));
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, TestConstants.FLOW_ID);
assertFlowExecutionOutcome(result.getOutcome());
@@ -542,10 +542,10 @@ public class OIDCTokenConsumerFlowTest extends AbstractOIDCTokenConsumerFlowTest
// Add cookies
input.addmember("http.headers.Cookie").unsafe_string(TestHelper.buildCookieHeader(
TestConstants.STATE_TOKEN,
- TestConstants.APPLICATION_ID,
+ TestConstants.APPLICATION_ID_REQUEST_OBJECT,
TestHelper.buildAuthenticationState(null, false, null), true));
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, TestConstants.FLOW_ID);
@@ -573,10 +573,10 @@ public class OIDCTokenConsumerFlowTest extends AbstractOIDCTokenConsumerFlowTest
// Add cookies
input.addmember("http.headers.Cookie").unsafe_string(TestHelper.buildCookieHeader(
TestConstants.STATE_TOKEN,
- TestConstants.APPLICATION_ID,
+ TestConstants.APPLICATION_ID_REQUEST_OBJECT,
TestHelper.buildAuthenticationState(null, false, null), true));
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, TestConstants.FLOW_ID);
@@ -599,10 +599,10 @@ public class OIDCTokenConsumerFlowTest extends AbstractOIDCTokenConsumerFlowTest
// Add cookies
input.addmember("http.headers.Cookie").unsafe_string(TestHelper.buildCookieHeader(
TestConstants.STATE_TOKEN,
- TestConstants.APPLICATION_ID,
+ TestConstants.APPLICATION_ID_REQUEST_OBJECT,
TestHelper.buildAuthenticationState(null, false, null), true));
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, TestConstants.FLOW_ID);
@@ -630,10 +630,10 @@ public class OIDCTokenConsumerFlowTest extends AbstractOIDCTokenConsumerFlowTest
// Add cookies
input.addmember("http.headers.Cookie").unsafe_string(TestHelper.buildCookieHeader(
TestConstants.STATE_TOKEN,
- TestConstants.APPLICATION_ID,
+ TestConstants.APPLICATION_ID_REQUEST_OBJECT,
TestHelper.buildAuthenticationState(null, false, null), true));
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, TestConstants.FLOW_ID);
@@ -654,10 +654,10 @@ public class OIDCTokenConsumerFlowTest extends AbstractOIDCTokenConsumerFlowTest
// Add cookies
inputSuccessResponse.addmember("http.headers.Cookie").unsafe_string(TestHelper.buildCookieHeader(
TestConstants.STATE_TOKEN,
- TestConstants.APPLICATION_ID,
+ TestConstants.APPLICATION_ID_REQUEST_OBJECT,
TestHelper.buildAuthenticationState(null, false, null), true));
- setApplicationRequest(TestConstants.APPLICATION_ID, inputSuccessResponse);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, inputSuccessResponse);
final FlowExecutionResult resultReplayFail =
flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
diff --git a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowUsingStorageServiceTest.java b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowUsingStorageServiceTest.java
index eb8b658..a3a5fd6 100644
--- a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowUsingStorageServiceTest.java
+++ b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowUsingStorageServiceTest.java
@@ -107,7 +107,7 @@ public class OIDCTokenConsumerFlowUsingStorageServiceTest extends AbstractOIDCTo
//TODO this is brittle
final StringBuilder builder = new StringBuilder(StorageServiceStateManager.class.getName());
- builder.append('!').append("testsp.example.org").append('!').append(TestConstants.APPLICATION_ID);
+ builder.append('!').append("testsp.example.org").append('!').append(TestConstants.APPLICATION_ID_REQUEST_OBJECT);
final String context = builder.toString();
storageService.create(context,
TestConstants.STATE_COOKIE_STORAGE_KEY, encoded,
@@ -136,10 +136,10 @@ public class OIDCTokenConsumerFlowUsingStorageServiceTest extends AbstractOIDCTo
// Add cookies
input.addmember("http.headers.Cookie").unsafe_string(TestHelper.buildCookieHeader(
TestConstants.STATE_TOKEN,
- TestConstants.APPLICATION_ID,
+ TestConstants.APPLICATION_ID_REQUEST_OBJECT,
TestConstants.STATE_COOKIE_STORAGE_KEY, false));
- setApplicationRequest(TestConstants.APPLICATION_ID, input);
+ setApplicationRequest(TestConstants.APPLICATION_ID_REQUEST_OBJECT, input);
final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, TestConstants.FLOW_ID);
diff --git a/sp-oidc-conf-impl/src/test/resources/metadata/openid-configuration.json b/sp-oidc-conf-impl/src/test/resources/metadata/openid-configuration.json
index 592e3b4..e6b8813 100644
--- a/sp-oidc-conf-impl/src/test/resources/metadata/openid-configuration.json
+++ b/sp-oidc-conf-impl/src/test/resources/metadata/openid-configuration.json
@@ -56,5 +56,7 @@
"grant_types_supported": [
"authorization_code",
"refresh_token"
-]
+],
+"end_session_endpoint":
+ "https://op.example.org/end_session"
}
\ No newline at end of file
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
new file mode 100644
index 0000000..4ae0dde
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AbstractLogoutRequestParameterValueMessageHandler.java
@@ -0,0 +1,204 @@
+/*
+ * 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.handler.AbstractMessageHandler;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.opensaml.profile.context.navigate.ParentProfileRequestContextLookup;
+
+import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
+
+import net.shibboleth.oidc.metadata.context.OIDCProviderMetadataContext;
+import net.shibboleth.oidc.profile.core.OIDCLogoutRequest;
+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;
+
+/**
+ * Base class for message handlers that process and apply values of OpenID Connect logout requests.
+ *
+ * <p>
+ * This abstract class provides common functionality for locating:
+ * </p>
+ * <ul>
+ * <li>the {@link OIDCLogoutRequest} 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>
+ *
+ * @param <T> the logout request parameter value type
+ *
+ * TODO: move to commons
+ */
+public abstract class AbstractLogoutRequestParameterValueMessageHandler<T> extends AbstractMessageHandler {
+
+ /** Lookup function for parent ProfileRequestContext. */
+ @Nonnull protected static final ParentProfileRequestContextLookup<MessageContext> PRC_LOOKUP
+ = new ParentProfileRequestContextLookup<>();
+
+ /** Strategy used to locate the {@link OIDCLogoutRequest}. */
+ @NonnullAfterInit private Function<MessageContext, OIDCLogoutRequest> logoutRequestLookupStrategy;
+
+ /** Lookup strategy to locate the OpenID Provider metadata to use.*/
+ @NonnullAfterInit private Function<MessageContext, OIDCProviderMetadataContext> providerMetadataLookupStrategy;
+
+ /** Lookup strategy for parameter value. */
+ @Nullable private Function<MessageContext,T> parameterValueLookupStrategy;
+
+ /** The logout request parameter value type.*/
+ @Nonnull private final Class<T> type;
+
+ /** The stashed {@link OIDCLogoutRequest}.*/
+ @NonnullBeforeExec private OIDCLogoutRequest logoutRequest;
+
+ /** The stashed OpenID Provider metadata .*/
+ @NonnullBeforeExec private OIDCProviderMetadata providerMetadata;
+
+
+ /**
+ * Constructor.
+ *
+ * @param valueType type of value returned by handler
+ */
+ protected AbstractLogoutRequestParameterValueMessageHandler(@Nonnull final Class<T> valueType) {
+ type = Constraint.isNotNull(valueType, "Logout request parameter value type cannot be null");
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+
+ if (logoutRequestLookupStrategy == null) {
+ throw new ComponentInitializationException("LogoutRequestLookupStrategy cannot be null");
+ }
+ if (providerMetadataLookupStrategy == null) {
+ throw new ComponentInitializationException("ProviderMetadataLookupStrategy cannot be null");
+ }
+ }
+
+ /**
+ * Get the logout request.
+ *
+ * @return the logout request
+ */
+ @NonnullBeforeExec protected OIDCLogoutRequest getLogoutRequest() {
+ return logoutRequest;
+ }
+
+ /**
+ * 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
+ * {@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 logout request.
+ *
+ * @param strategy The parameter value lookup strategy to set.
+ */
+ public void setParameterValueLookupStrategy(@Nonnull final Function<MessageContext, T> strategy) {
+ checkSetterPreconditions();
+ parameterValueLookupStrategy = Constraint.isNotNull(strategy,
+ "ParameterValueLookupStrategy can not be null");
+ }
+
+ /**
+ * Retrieves the parameter value or configuration options from the configured lookup strategy,
+ * verifying at runtime that the result matches the type expected by the subclass.
+ *
+ * @param context the message context to pass to the lookup function
+ *
+ * @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("Logout request parameter value lookup returned the "
+ + "wrong value type");
+ }
+
+ /**
+ * Set the strategy used to locate the {@link OIDCLogoutRequest} to use.
+ *
+ * @param strategy lookup strategy
+ */
+ public void setLogoutRequestLookupStrategy(
+ @Nonnull final Function<MessageContext, OIDCLogoutRequest> strategy) {
+ checkSetterPreconditions();
+
+ logoutRequestLookupStrategy =
+ Constraint.isNotNull(strategy, "LogoutContext lookup strategy cannot be null");
+ }
+
+ @Override
+ protected boolean doPreInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+
+ logoutRequest = logoutRequestLookupStrategy.apply(messageContext);
+ if (logoutRequest == null) {
+ throw new MessageHandlerException("OIDC logout 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/profile/impl/AddClientIDHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddClientIDHandler.java
new file mode 100644
index 0000000..87d21e9
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddClientIDHandler.java
@@ -0,0 +1,50 @@
+/*
+ * 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.messaging.handler.MessageHandlerException;
+import org.slf4j.Logger;
+
+import com.nimbusds.oauth2.sdk.id.ClientID;
+
+import net.shibboleth.shared.primitive.LoggerFactory;
+
+/**
+ * A message handler that populates the client_id parameter into the logout request.
+ */
+public class AddClientIDHandler extends AbstractLogoutRequestParameterValueMessageHandler<String> {
+
+ /** Logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddClientIDHandler.class);
+
+ /** Constructor.*/
+ public AddClientIDHandler() {
+ super(String.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ 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);
+ }
+ }
+}
\ 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
new file mode 100644
index 0000000..44be868
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddIDTokenHintHandler.java
@@ -0,0 +1,52 @@
+/*
+ * 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.messaging.handler.MessageHandlerException;
+import org.slf4j.Logger;
+
+import com.nimbusds.jwt.JWT;
+
+import net.shibboleth.shared.primitive.LoggerFactory;
+
+/**
+ * A message handler that populates the login_hint parameter into the logout request.
+ */
+public class AddIDTokenHintHandler extends AbstractLogoutRequestParameterValueMessageHandler<JWT> {
+
+ /** Logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddIDTokenHintHandler.class);
+
+ /** Constructor.*/
+ public AddIDTokenHintHandler() {
+ super(JWT.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+
+ final JWT idTokenHint = getParameterValue(messageContext);
+ getLogoutRequest().setIdTokenHint(idTokenHint);
+ log.trace("{}: Set id_token_hint to '{}'", getLogPrefix(), idTokenHint);
+
+ }
+
+
+
+}
\ 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/AddLoginHintHandler.java
new file mode 100644
index 0000000..49543e3
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddLoginHintHandler.java
@@ -0,0 +1,50 @@
+/*
+ * 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.messaging.handler.MessageHandlerException;
+import org.slf4j.Logger;
+
+import net.shibboleth.shared.primitive.LoggerFactory;
+
+/**
+ * A message handler that populates the login_hint parameter into the logout request.
+ */
+public class AddLoginHintHandler extends AbstractLogoutRequestParameterValueMessageHandler<String> {
+
+ /** Logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddLoginHintHandler.class);
+
+ /** Constructor.*/
+ public AddLoginHintHandler() {
+ super(String.class);
+ }
+
+ /** {@inheritDoc} */
+ @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);
+
+ }
+
+
+
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..b560b0a
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddPostLogoutRedirectURIHandler.java
@@ -0,0 +1,52 @@
+/*
+ * 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.Nonnull;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.slf4j.Logger;
+
+import net.shibboleth.shared.primitive.LoggerFactory;
+
+/**
+ * A message handler that populates the client_id parameter into the logout request.
+ */
+public class AddPostLogoutRedirectURIHandler extends AbstractLogoutRequestParameterValueMessageHandler<URI> {
+
+ /** Logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddPostLogoutRedirectURIHandler.class);
+
+ /** Constructor.*/
+ public AddPostLogoutRedirectURIHandler() {
+ super(URI.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+
+ final URI postRedirectUri = getParameterValue(messageContext);
+ getLogoutRequest().setPostLogoutRedirectURI(postRedirectUri);
+ log.trace("{}: Set post_logout_redirect_uri to '{}'", getLogPrefix(), postRedirectUri);
+
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddUILocalesHandler.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddUILocalesHandler.java
new file mode 100644
index 0000000..6691be0
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/AddUILocalesHandler.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 java.util.List;
+import java.util.Objects;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.slf4j.Logger;
+
+import com.nimbusds.langtag.LangTag;
+import com.nimbusds.langtag.LangTagException;
+
+import net.shibboleth.shared.primitive.LoggerFactory;
+
+/**
+ * A message handler that populates the client_id parameter into the logout request.
+ */
+public class AddUILocalesHandler extends AbstractLogoutRequestParameterValueMessageHandler<List<String>> {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddUILocalesHandler.class);
+
+ /** Constructor.*/
+ public AddUILocalesHandler() {
+ super((Class)List.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+
+ final List<String> locales = getParameterValue(messageContext);
+ if (locales != null && !locales.isEmpty()) {
+ if (log.isTraceEnabled()) {
+ log.trace("{} Setting 'ui_locales={}'", getLogPrefix(), locales);
+ }
+ final List<LangTag> uiLocals = locales.stream().map(tag -> {
+ try {
+ return LangTag.parse(tag);
+ } catch (final LangTagException e) {
+ log.warn("Can not parse language tag '{}'", tag);
+ }
+ return null;
+ }).filter(Objects::nonNull).toList();
+
+ getLogoutRequest().setUiLocales(uiLocals);
+ }
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/InitializeLogoutRequest.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/InitializeLogoutRequest.java
new file mode 100644
index 0000000..df9d0d0
--- /dev/null
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/InitializeLogoutRequest.java
@@ -0,0 +1,151 @@
+/*
+ * 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.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.profile.action.ActionSupport;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+
+import net.shibboleth.idp.profile.AbstractProfileAction;
+import net.shibboleth.idp.profile.IdPEventIds;
+import net.shibboleth.oidc.profile.core.OIDCLogoutRequest;
+import net.shibboleth.oidc.profile.core.OidcEventIds;
+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;
+
+/**
+ * An action that creates an {@link OIDCLogoutRequest} shell to populate in future steps,
+ * and sets it to the outbound message context.
+ *
+ * <p>When creating the shell, the logout endpoint of the OpenID Provider is resolved, typically from metadata..
+ * If no metadata is found, or the logout endpoint is not set, an error event will be emitted. If there is nowhere
+ * to send the request, there is no point in trying to build it.</p>
+ *
+ * @event {@link org.opensaml.profile.action.EventIds#PROCEED_EVENT_ID}
+ * @event {@link IdPEventIds#INVALID_PROFILE_CONFIG}
+ * @event {@link OidcEventIds#MISSING_END_SESSION_ENDPOINT}
+ * @post Add an {@link OIDCLogoutRequest} as the message of the outbound context.
+ */
+public class InitializeLogoutRequest extends AbstractProfileAction {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(InitializeLogoutRequest.class);
+
+ /** Strategy function for access to {@link RelyingPartyContext}. */
+ @Nonnull private Function<ProfileRequestContext,RelyingPartyContext> relyingPartyContextLookupStrategy;
+
+ /** Strategy to find the logout endpoint. Typically taken from the OP's metadata, but can come via other means.*/
+ @NonnullAfterInit private Function<ProfileRequestContext, URI> logoutEndpointLookupStrategy;
+
+ /** The stashed outbound message context. */
+ @NonnullBeforeExec private MessageContext outMessageContext;
+
+ /** Optional RP name for logging. */
+ @Nullable private String relyingPartyId;
+
+ /** Constructor.*/
+ public InitializeLogoutRequest() {
+ relyingPartyContextLookupStrategy = new ChildContextLookup<>(RelyingPartyContext.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+
+ if (logoutEndpointLookupStrategy == null) {
+ throw new ComponentInitializationException("LogoutEndpointLookupStrategy cannot be null");
+ }
+ }
+
+ /**
+ * Set the strategy used to locate the logout endpoint URI.
+ *
+ * @param strategy the strategy.
+ */
+ public void setLogoutEndpointLookupStrategy(@Nonnull final Function<ProfileRequestContext, URI> strategy) {
+ checkSetterPreconditions();
+
+ logoutEndpointLookupStrategy =
+ Constraint.isNotNull(strategy, "LogoutEndpointLookupStrategy can not be null");
+ }
+
+ /**
+ * Set lookup strategy for {@link RelyingPartyContext}.
+ *
+ * @param strategy lookup strategy
+ */
+ public void setRelyingPartyContextLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext,RelyingPartyContext> strategy) {
+ checkSetterPreconditions();
+ relyingPartyContextLookupStrategy = Constraint.isNotNull(strategy,
+ "RelyingPartyContext lookup strategy cannot be null");
+ }
+
+ @Override
+ protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
+
+ if (!super.doPreExecute(profileRequestContext)) {
+ return false;
+ }
+
+ outMessageContext = profileRequestContext.getOutboundMessageContext();
+ if (outMessageContext == null) {
+ log.error("{} Outbound message context not found", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, IdPEventIds.INVALID_PROFILE_CONFIG);
+ return false;
+ }
+
+
+ final RelyingPartyContext rpContext = relyingPartyContextLookupStrategy.apply(profileRequestContext);
+ if (rpContext != null) {
+ relyingPartyId = rpContext.getRelyingPartyId();
+ }
+
+ return true;
+ }
+
+ @Override
+ protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
+ super.doExecute(profileRequestContext);
+
+ final URI logoutEndpoint = logoutEndpointLookupStrategy.apply(profileRequestContext);
+ if (logoutEndpoint == null) {
+ log.warn("{} Unable to resolve logout endpoint for outbound messag '{}'",
+ getLogPrefix(), relyingPartyId);
+ ActionSupport.buildEvent(profileRequestContext, OidcEventIds.MISSING_END_SESSION_ENDPOINT);
+ return;
+ }
+ final OIDCLogoutRequest logoutRequest = new OIDCLogoutRequest(logoutEndpoint);
+
+ outMessageContext.setMessage(logoutRequest);
+ log.debug("{} Adding shell OIDC logout request to outbound context for client '{}'", getLogPrefix(),
+ relyingPartyId);
+
+ }
+
+}
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 57bfb65..02cec41 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
@@ -39,7 +39,7 @@ import net.shibboleth.shared.primitive.LoggerFactory;
/**
* Initialize an outbound message context with an OIDC peer entity context ready for an authorization/authentication
- * request to be built.
+ * request to be built. Constructs the outbound peer entity context based on that found RelyingPartyContext.
*
* TODO self context
*
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/InitializeRelyingPartyContextFromOIDCPeer.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/InitializeRelyingPartyContextFromOIDCPeer.java
index 9b035d1..43108f7 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/InitializeRelyingPartyContextFromOIDCPeer.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/InitializeRelyingPartyContextFromOIDCPeer.java
@@ -156,6 +156,8 @@ public class InitializeRelyingPartyContextFromOIDCPeer extends AbstractProfileAc
log.debug("{} Attaching RelyingPartyContext based on OIDC peer '{}'", getLogPrefix(),
peerEntityCtx.getIdentifier());
+ // TODO, this is redundant if we've already set the relying party ID in the context by this point e.g. logout
+ // TODO We could set the relying Party ID strategy here, which by default pulls it out of the peerContext see InitializeRelyingPartyContextFromSAMLPeer
rpContext.setRelyingPartyId(peerEntityCtx.getIdentifier());
rpContext.setRelyingPartyIdContextTree(peerEntityCtx);
final OIDCProviderMetadataContext oidcContext =
diff --git a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ProcessLogoutInitiatorRequest.java b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ProcessLogoutInitiatorRequest.java
index 8928ea5..471cd68 100644
--- a/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ProcessLogoutInitiatorRequest.java
+++ b/sp-oidc-impl/src/main/java/net/shibboleth/sp/oidc/profile/impl/ProcessLogoutInitiatorRequest.java
@@ -159,6 +159,8 @@ public class ProcessLogoutInitiatorRequest extends AbstractApplicationAction {
final JWTClaimsSet claims = localIdToken.getJWTClaimsSet();
if (claims != null) {
relyingPartyId = claims.getIssuer();
+ log.trace("{} Set RelyingPartyID to '{}' based on issuer '{}' in recovered ID Token",
+ getLogPrefix(), relyingPartyId, claims.getIssuer());
}
if (relyingPartyId == null) {
ActionSupport.buildEvent(profileRequestContext, EventIds.UNABLE_TO_DECODE);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list