[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