[java-plugin-shibd-saml] branch main updated: JSHIBDSAML-1 - Request/response correlation and passive tracking
Scott Cantor
cantor.2 at osu.edu
Wed Apr 16 14:05:44 UTC 2025
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch main
in repository java-plugin-shibd-saml.
View the commit online:
http://git.shibboleth.net/view/?p=java-plugin-shibd-saml.git;a=commit;h=0cd4bbce99ed5cd1e689e5b26fac94b77e725367
The following commit(s) were added to refs/heads/main by this push:
new 0cd4bbc JSHIBDSAML-1 - Request/response correlation and passive tracking
0cd4bbc is described below
commit 0cd4bbce99ed5cd1e689e5b26fac94b77e725367
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Apr 16 10:05:42 2025 -0400
JSHIBDSAML-1 - Request/response correlation and passive tracking
https://shibboleth.atlassian.net/browse/JSHIBDSAML-1
Bit the bullet and added dedicated option controlling unsolicited SSO.
---
.../config/BrowserSSOProfileConfiguration.java | 19 +++++++++
.../config/logic/AllowUnsolicitedPredicate.java | 48 ++++++++++++++++++++++
.../saml2/profile/config/logic/package-info.java | 18 ++++++++
.../idp/flows/sp/consumer/saml2/saml2-beans.xml | 8 +++-
.../net/shibboleth/sp/service/agent/postconfig.xml | 3 +-
.../shibboleth/idp/module/conf/sp/saml.properties | 6 ++-
.../impl/BrowserSSOProfileConfiguration.java | 34 ++++++++++++++-
7 files changed, 130 insertions(+), 6 deletions(-)
diff --git a/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/profile/config/BrowserSSOProfileConfiguration.java b/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/profile/config/BrowserSSOProfileConfiguration.java
index d38b311..82576ed 100644
--- a/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/profile/config/BrowserSSOProfileConfiguration.java
+++ b/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/profile/config/BrowserSSOProfileConfiguration.java
@@ -23,6 +23,7 @@ import javax.annotation.Nullable;
import net.shibboleth.idp.attribute.IdPAttribute;
import net.shibboleth.saml.profile.config.SAMLArtifactConsumerProfileConfiguration;
+import net.shibboleth.shared.annotation.ConfigurationSetting;
import net.shibboleth.shared.annotation.constraint.NonnullElements;
import net.shibboleth.shared.annotation.constraint.NotLive;
import net.shibboleth.shared.annotation.constraint.Unmodifiable;
@@ -31,11 +32,23 @@ import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.saml.common.xml.SAMLConstants;
import org.opensaml.saml.saml2.core.AuthnContextClassRef;
import org.opensaml.saml.saml2.core.AuthnRequest;
+import org.opensaml.saml.saml2.core.SubjectConfirmationData;
/** Configuration support for SP SAML 2.0 Browser SSO. */
public interface BrowserSSOProfileConfiguration extends SAMLArtifactConsumerProfileConfiguration,
net.shibboleth.saml.saml2.profile.config.BrowserSSOProfileConfiguration {
+ /**
+ * Get whether the inbound {@link SubjectConfirmationData#getInResponseTo()} value
+ * may be empty, i.e., allowing the receipt of unsolicited responses.
+ *
+ * @param profileRequestContext current profile request context
+ *
+ * @return whether to allow unsolicited SSO
+ */
+ @ConfigurationSetting(name="allowUnsolicited")
+ boolean isAllowUnsolicited(@Nullable final ProfileRequestContext profileRequestContext);
+
/**
* Get the {@link AuthnContextClassRef} values to include in SAML request.
*
@@ -43,6 +56,7 @@ public interface BrowserSSOProfileConfiguration extends SAMLArtifactConsumerProf
*
* @return list of class references
*/
+ @ConfigurationSetting(name="authnContextClassRefs")
@Nonnull @NonnullElements @NotLive @Unmodifiable List<String> getAuthnContextClassRefs(
@Nullable final ProfileRequestContext profileRequestContext);
@@ -53,6 +67,7 @@ public interface BrowserSSOProfileConfiguration extends SAMLArtifactConsumerProf
*
* @return required format
*/
+ @ConfigurationSetting(name="nameIDFormat")
@Nullable String getNameIDFormat(@Nullable final ProfileRequestContext profileRequestContext);
/**
@@ -64,6 +79,7 @@ public interface BrowserSSOProfileConfiguration extends SAMLArtifactConsumerProf
*
* @return response binding
*/
+ @ConfigurationSetting(name="responseBinding")
@Nullable String getResponseBinding(@Nullable final ProfileRequestContext profileRequestContext);
/**
@@ -79,6 +95,7 @@ public interface BrowserSSOProfileConfiguration extends SAMLArtifactConsumerProf
*
* @return whether to perform standard data extraction
*/
+ @ConfigurationSetting(name="extractStandardAttributes")
boolean isExtractStandardAttributes(@Nullable final ProfileRequestContext profileRequestContext);
/**
@@ -92,6 +109,7 @@ public interface BrowserSSOProfileConfiguration extends SAMLArtifactConsumerProf
*
* @return extraction strategy
*/
+ @ConfigurationSetting(name="attributeExtractionStrategy")
@Nullable Function<ProfileRequestContext,Collection<IdPAttribute>> getAttributeExtractionStrategy(
@Nullable final ProfileRequestContext profileRequestContext);
@@ -102,6 +120,7 @@ public interface BrowserSSOProfileConfiguration extends SAMLArtifactConsumerProf
*
* @return principal name to use during resolution
*/
+ @ConfigurationSetting(name="attributeResolutionPrincipal")
@Nullable String getAttributeResolutionPrincipal(@Nullable final ProfileRequestContext profileRequestContext);
}
\ No newline at end of file
diff --git a/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/profile/config/logic/AllowUnsolicitedPredicate.java b/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/profile/config/logic/AllowUnsolicitedPredicate.java
new file mode 100644
index 0000000..e61af9c
--- /dev/null
+++ b/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/profile/config/logic/AllowUnsolicitedPredicate.java
@@ -0,0 +1,48 @@
+/*
+ * 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.saml.saml2.profile.config.logic;
+
+import javax.annotation.Nullable;
+
+import net.shibboleth.profile.context.RelyingPartyContext;
+import net.shibboleth.profile.context.logic.AbstractRelyingPartyPredicate;
+import net.shibboleth.sp.saml.saml2.profile.config.BrowserSSOProfileConfiguration;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+/**
+ * A predicate that evaluates a {@link ProfileRequestContext} and extracts the effective
+ * setting of {@link BrowserSSOProfileConfiguration#isAllowUnsolicited(ProfileRequestContext)}.
+ *
+ * <p>Defaults to false.</p>
+ *
+ * @since 5.2.0
+ */
+public class AllowUnsolicitedPredicate extends AbstractRelyingPartyPredicate {
+
+ /** {@inheritDoc} */
+ public boolean test(@Nullable final ProfileRequestContext input) {
+
+ final RelyingPartyContext rpc = getRelyingPartyContext(input);
+ if (rpc != null) {
+ if (rpc.getProfileConfig() instanceof BrowserSSOProfileConfiguration sso) {
+ return sso.isAllowUnsolicited(input);
+ }
+ }
+
+ return false;
+ }
+
+}
\ No newline at end of file
diff --git a/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/profile/config/logic/package-info.java b/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/profile/config/logic/package-info.java
new file mode 100644
index 0000000..de512b8
--- /dev/null
+++ b/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/profile/config/logic/package-info.java
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
+
+/**
+ * Predicates related to SAML 2.0 SP profile configuration.
+ */
+package net.shibboleth.sp.saml.saml2.profile.config.logic;
\ No newline at end of file
diff --git a/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/saml2/saml2-beans.xml b/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/saml2/saml2-beans.xml
index 52e7ae1..7f8a946 100644
--- a/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/saml2/saml2-beans.xml
+++ b/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/saml2/saml2-beans.xml
@@ -151,9 +151,13 @@
<property name="checkAddress">
<bean class="net.shibboleth.saml.saml2.profile.config.logic.CheckAddressPredicate" />
</property>
- <!-- This effectively determines whether unsolicited responses work. -->
+ <!-- This determines whether unsolicited responses are allowed. -->
<property name="inResponseToRequired">
- <bean class="net.shibboleth.saml.saml2.profile.config.logic.CheckInResponseToPredicate" />
+ <bean parent="shibboleth.Conditions.NOT">
+ <constructor-arg>
+ <bean class="net.shibboleth.sp.saml.saml2.profile.config.logic.AllowUnsolicitedPredicate" />
+ </constructor-arg>
+ </bean>
</property>
<!-- This accomodates broken IdPs or problems getting correlation to work. -->
<property name="inResponseToIgnored">
diff --git a/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/sp/service/agent/postconfig.xml b/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/sp/service/agent/postconfig.xml
index ce2ed0b..1a41d04 100644
--- a/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/sp/service/agent/postconfig.xml
+++ b/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/sp/service/agent/postconfig.xml
@@ -29,7 +29,8 @@
p:securityConfiguration-ref="shibboleth.DefaultXMLSecurityConfiguration"
p:encryptionOptionalPredicate="%{sp.saml.encryption.optional:true}"
p:checkAddress="%{sp.saml.checkAddress:true}"
- p:checkInResponseTo="%{sp.saml.checkInResoonseTo:false}"
+ p:checkInResponseTo="%{sp.saml.checkInResoonseTo:true}"
+ p:allowUnsolicited="%{sp.saml.allowUnsolicited:true}"
p:extractStandardAttributes="%{sp.saml.extractStandardAttributes:false}" />
<util:constant id="SAML2.SSO.FEATURE_AUTHNCONTEXT"
diff --git a/sp-saml-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/sp/saml.properties b/sp-saml-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/sp/saml.properties
index e2a6aec..0138408 100644
--- a/sp-saml-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/sp/saml.properties
+++ b/sp-saml-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/sp/saml.properties
@@ -15,10 +15,12 @@ sp.saml.encryption.cert = %{idp.home}/credentials/sp/sp-encryption.crt
# TODO: The next two are global only at the moment.
#sp.saml.checkRecipient = true
#sp.saml.checkNotOnOrAfter = true
+# Turn off to disallow unsolicited SSO responses
+#sp.saml.allowUnsolicited = true
# Turn off to disable address check during assertion validation
#sp.saml.checkAddress = true
-# Turn on to disallow unsolicited SSO responses
-#sp.saml.checkInResponseTo = false
+# Turn off to disable message correlation checking
+#sp.saml.checkInResponseTo = true
# Default security configuration for SAML
diff --git a/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/config/impl/BrowserSSOProfileConfiguration.java b/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/config/impl/BrowserSSOProfileConfiguration.java
index 6393f31..0f85ff9 100644
--- a/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/config/impl/BrowserSSOProfileConfiguration.java
+++ b/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/config/impl/BrowserSSOProfileConfiguration.java
@@ -61,7 +61,10 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML2AssertionConsum
/** Whether to validate inbound InResponseTo values. */
@Nonnull private Predicate<ProfileRequestContext> checkInResponseToPredicate;
-
+
+ /** Whether to allow empty InResponseTo values. */
+ @Nonnull private Predicate<ProfileRequestContext> allowUnsolicitedPredicate;
+
/** Lookup function to supply maximum time since inbound AuthnInstant. */
@Nonnull private Function<ProfileRequestContext,Duration> maximumTimeSinceAuthnLookupStrategy;
@@ -117,6 +120,7 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML2AssertionConsum
forceAuthnPredicate = PredicateSupport.alwaysFalse();
checkAddressPredicate = PredicateSupport.alwaysTrue();
checkInResponseToPredicate = PredicateSupport.alwaysTrue();
+ allowUnsolicitedPredicate = PredicateSupport.alwaysTrue();
maximumTimeSinceAuthnLookupStrategy = FunctionSupport.constant(null);
proxyCountLookupStrategy = FunctionSupport.constant(null);
authnContextComparisonLookupStrategy = FunctionSupport.constant(null);
@@ -252,6 +256,34 @@ public class BrowserSSOProfileConfiguration extends AbstractSAML2AssertionConsum
checkInResponseToPredicate = Constraint.isNotNull(condition, "InResponseTo checking predicate cannot be null");
}
+ /** {@inheritDoc} */
+ public boolean isAllowUnsolicited(@Nullable final ProfileRequestContext profileRequestContext) {
+ return allowUnsolicitedPredicate.test(profileRequestContext);
+ }
+
+ /**
+ * Sets whether to allow unsolicited SSO responses (i.e., explicitly allow an empty InResponseTo value).
+ *
+ * <p>Defaults to true.</p>
+ *
+ * @param flag flag to set
+ */
+ public void setAllowUnsolicited(final boolean flag) {
+ allowUnsolicitedPredicate = PredicateSupport.constant(flag);
+ }
+
+ /**
+ * Sets the condition for whether to allow unsolicited SSO responses (i.e., explicitly allow an empty InResponseTo
+ * value).
+ *
+ * <p>Defaults to true.</p>
+ *
+ * @param condition condition to set
+ */
+ public void setAllowUnsolicitedPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
+ allowUnsolicitedPredicate = Constraint.isNotNull(condition, "Unsolicited response predicate cannot be null");
+ }
+
/** {@inheritDoc} */
@Nullable public Duration getMaximumTimeSinceAuthn(@Nullable final ProfileRequestContext profileRequestContext) {
final Duration amount = maximumTimeSinceAuthnLookupStrategy.apply(profileRequestContext);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list