From bf5dd9c5dda40d72e6b399679f96065597cac6c8 Mon Sep 17 00:00:00 2001 From: abhisek Date: Mon, 29 Nov 2021 23:11:12 +0530 Subject: [PATCH 1/3] Add settings to control destination URL validation --- .../onelogin/saml2/authn/SamlResponse.java | 2 +- .../saml2/settings/Saml2Settings.java | 19 +++++++++++++++++++ .../saml2/settings/SettingsBuilder.java | 5 +++++ .../saml2/test/authn/AuthnResponseTest.java | 5 +++++ .../test/settings/Saml2SettingsTest.java | 12 ++++++++++++ .../test/settings/SettingBuilderTest.java | 6 ++++++ 6 files changed, 48 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/com/onelogin/saml2/authn/SamlResponse.java b/core/src/main/java/com/onelogin/saml2/authn/SamlResponse.java index 8fc66d8a..6f3945aa 100644 --- a/core/src/main/java/com/onelogin/saml2/authn/SamlResponse.java +++ b/core/src/main/java/com/onelogin/saml2/authn/SamlResponse.java @@ -1281,7 +1281,7 @@ protected void validateAudiences() throws XPathExpressionException, ValidationEr * @throws ValidationError */ protected void validateDestination(final Element element) throws ValidationError { - if (element.hasAttribute("Destination")) { + if (settings.getWantDestinationUrlValidation() && element.hasAttribute("Destination")) { final String destinationUrl = element.getAttribute("Destination"); if (destinationUrl != null) { if (destinationUrl.isEmpty()) { diff --git a/core/src/main/java/com/onelogin/saml2/settings/Saml2Settings.java b/core/src/main/java/com/onelogin/saml2/settings/Saml2Settings.java index 9ee29465..1977513a 100644 --- a/core/src/main/java/com/onelogin/saml2/settings/Saml2Settings.java +++ b/core/src/main/java/com/onelogin/saml2/settings/Saml2Settings.java @@ -76,6 +76,7 @@ public class Saml2Settings { private List requestedAuthnContext = new ArrayList<>(); private String requestedAuthnContextComparison = "exact"; private boolean wantXMLValidation = true; + private boolean wantDestinationUrlValidation = true; private String signatureAlgorithm = Constants.RSA_SHA1; private String digestAlgorithm = Constants.SHA1; private boolean rejectUnsolicitedResponsesWithInResponseTo = false; @@ -346,6 +347,13 @@ public boolean getWantXMLValidation() { return wantXMLValidation; } + /** + * @return the wantDestinationUrlValidation setting value + */ + public boolean getWantDestinationUrlValidation() { + return wantDestinationUrlValidation; + } + /** * @return the signatureAlgorithm setting value */ @@ -776,6 +784,17 @@ public void setWantXMLValidation(boolean wantXMLValidation) { this.wantXMLValidation = wantXMLValidation; } + /** + * Set the wantDestinationUrlValidation setting value + * + * @param wantDestinationUrlValidation + * the wantDestinationUrlValidation value to be set. + * Based on it the SP will validate Destination attribute in SAML response XML. + */ + public void setDestinationUrlValidation(boolean wantDestinationUrlValidation) { + this.wantDestinationUrlValidation = wantDestinationUrlValidation; + } + /** * Set the signatureAlgorithm setting value * diff --git a/core/src/main/java/com/onelogin/saml2/settings/SettingsBuilder.java b/core/src/main/java/com/onelogin/saml2/settings/SettingsBuilder.java index 6232044e..e7b95ff0 100644 --- a/core/src/main/java/com/onelogin/saml2/settings/SettingsBuilder.java +++ b/core/src/main/java/com/onelogin/saml2/settings/SettingsBuilder.java @@ -114,6 +114,7 @@ public class SettingsBuilder { public final static String SECURITY_REQUESTED_AUTHNCONTEXT = "onelogin.saml2.security.requested_authncontext"; public final static String SECURITY_REQUESTED_AUTHNCONTEXTCOMPARISON = "onelogin.saml2.security.requested_authncontextcomparison"; public final static String SECURITY_WANT_XML_VALIDATION = "onelogin.saml2.security.want_xml_validation"; + public final static String SECURITY_WANT_DESTINATION_URL_VALIDATION = "onelogin.saml2.security.want_destination_url_validation"; public final static String SECURITY_SIGNATURE_ALGORITHM = "onelogin.saml2.security.signature_algorithm"; public final static String SECURITY_DIGEST_ALGORITHM = "onelogin.saml2.security.digest_algorithm"; public final static String SECURITY_REJECT_UNSOLICITED_RESPONSES_WITH_INRESPONSETO = "onelogin.saml2.security.reject_unsolicited_responses_with_inresponseto"; @@ -399,6 +400,10 @@ private void loadSecuritySetting() { if (wantXMLValidation != null) saml2Setting.setWantXMLValidation(wantXMLValidation); + Boolean wantDestinationUrlvalidation = loadBooleanProperty(SECURITY_WANT_DESTINATION_URL_VALIDATION); + if (wantDestinationUrlvalidation != null) + saml2Setting.setDestinationUrlValidation(wantDestinationUrlvalidation); + Boolean signMetadata = loadBooleanProperty(SECURITY_SIGN_METADATA); if (signMetadata != null) saml2Setting.setSignMetadata(signMetadata); diff --git a/core/src/test/java/com/onelogin/saml2/test/authn/AuthnResponseTest.java b/core/src/test/java/com/onelogin/saml2/test/authn/AuthnResponseTest.java index 3d960ca7..7632be9c 100644 --- a/core/src/test/java/com/onelogin/saml2/test/authn/AuthnResponseTest.java +++ b/core/src/test/java/com/onelogin/saml2/test/authn/AuthnResponseTest.java @@ -1946,6 +1946,11 @@ public void testIsInValidDestination() throws IOException, Error, XPathExpressio samlResponse.setDestinationUrl(ACS_URL); samlResponse.isValid(); assertThat(samlResponse.getError(), not(containsString("The response was received at"))); + + settings.setDestinationUrlValidation(false); + samlResponse = new SamlResponse(settings, newHttpRequest(requestURL, samlResponseEncoded)); + samlResponse.isValid(); + assertThat(samlResponse.getError(), not(containsString("The response was received at"))); } /** diff --git a/core/src/test/java/com/onelogin/saml2/test/settings/Saml2SettingsTest.java b/core/src/test/java/com/onelogin/saml2/test/settings/Saml2SettingsTest.java index 67bbf84b..d45f0f6c 100644 --- a/core/src/test/java/com/onelogin/saml2/test/settings/Saml2SettingsTest.java +++ b/core/src/test/java/com/onelogin/saml2/test/settings/Saml2SettingsTest.java @@ -491,4 +491,16 @@ public void testValidateMetadataExpired() throws Exception { assertFalse(errors.isEmpty()); assertTrue(errors.contains("expired_xml")); } + + /** + * Tests the wantDestinationUrlValidation method of Saml2Settings + */ + @Test + public void testIsWantDestinationUrlValidation() { + Saml2Settings settings = new Saml2Settings(); + + assertTrue(settings.getWantDestinationUrlValidation()); + settings.setDestinationUrlValidation(false); + assertFalse(settings.getWantDestinationUrlValidation()); + } } diff --git a/core/src/test/java/com/onelogin/saml2/test/settings/SettingBuilderTest.java b/core/src/test/java/com/onelogin/saml2/test/settings/SettingBuilderTest.java index b9206d4f..765eaab7 100644 --- a/core/src/test/java/com/onelogin/saml2/test/settings/SettingBuilderTest.java +++ b/core/src/test/java/com/onelogin/saml2/test/settings/SettingBuilderTest.java @@ -843,6 +843,7 @@ public void testLoadFromValues() throws Exception { assertTrue(setting.getWantAssertionsSigned()); assertTrue(setting.getWantAssertionsEncrypted()); assertTrue(setting.getWantNameIdEncrypted()); + assertTrue(setting.getWantDestinationUrlValidation()); List reqAuthContext = new ArrayList<>(); reqAuthContext.add("urn:oasis:names:tc:SAML:2.0:ac:classes:urn:oasis:names:tc:SAML:2.0:ac:classes:Password"); @@ -925,6 +926,10 @@ public void testLoadFromValues() throws Exception { assertFalse(previousCert.equals(newCert)); assertFalse(previousKey.equals(newKey)); + samlData.put(SECURITY_WANT_DESTINATION_URL_VALIDATION, false); + + setting = new SettingsBuilder().fromValues(samlData).build(); + assertFalse(setting.getWantDestinationUrlValidation()); } /** @@ -1045,6 +1050,7 @@ public void testLoadFromValuesWithObjects() throws Exception { assertTrue(setting.getWantAssertionsSigned()); assertTrue(setting.getWantAssertionsEncrypted()); assertTrue(setting.getWantNameIdEncrypted()); + assertTrue(setting.getWantDestinationUrlValidation()); List reqAuthContext = new ArrayList<>(); reqAuthContext.add("urn:oasis:names:tc:SAML:2.0:ac:classes:urn:oasis:names:tc:SAML:2.0:ac:classes:Password"); From f1fa53f2b4d7bd937bc9653ceb4319991803001b Mon Sep 17 00:00:00 2001 From: abhisek Date: Mon, 29 Nov 2021 23:19:45 +0530 Subject: [PATCH 2/3] Update README with onelogin.saml2.security.want_destination_url_validation example --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index df0c3bf0..9bad45f1 100644 --- a/README.md +++ b/README.md @@ -371,6 +371,10 @@ onelogin.saml2.security.allow_duplicated_attribute_name = false # (In order to validate the xml, 'strict' and 'wantXMLValidation' must be true). onelogin.saml2.security.want_xml_validation = true +# Indicates if the SP will validate 'Destination' attribute in SAML response +# Both 'strict' and 'wantDestinationUrlValidation' must be true +onelogin.saml2.security.want_destination_url_validation = true + # Algorithm that the toolkit will use on signing process. Options: # 'http://www.w3.org/2000/09/xmldsig#rsa-sha1' # 'http://www.w3.org/2000/09/xmldsig#dsa-sha1' From 7f3975c13fbd6227bb6db0d8d7573b80c46162dd Mon Sep 17 00:00:00 2001 From: abhisek Date: Tue, 30 Nov 2021 16:26:12 +0530 Subject: [PATCH 3/3] Refactor setter name for destination url validator setting --- .../main/java/com/onelogin/saml2/settings/Saml2Settings.java | 2 +- .../main/java/com/onelogin/saml2/settings/SettingsBuilder.java | 2 +- .../java/com/onelogin/saml2/test/authn/AuthnResponseTest.java | 3 +-- .../com/onelogin/saml2/test/settings/Saml2SettingsTest.java | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/com/onelogin/saml2/settings/Saml2Settings.java b/core/src/main/java/com/onelogin/saml2/settings/Saml2Settings.java index 1977513a..7b57eb56 100644 --- a/core/src/main/java/com/onelogin/saml2/settings/Saml2Settings.java +++ b/core/src/main/java/com/onelogin/saml2/settings/Saml2Settings.java @@ -791,7 +791,7 @@ public void setWantXMLValidation(boolean wantXMLValidation) { * the wantDestinationUrlValidation value to be set. * Based on it the SP will validate Destination attribute in SAML response XML. */ - public void setDestinationUrlValidation(boolean wantDestinationUrlValidation) { + public void setWantDestinationUrlValidation(boolean wantDestinationUrlValidation) { this.wantDestinationUrlValidation = wantDestinationUrlValidation; } diff --git a/core/src/main/java/com/onelogin/saml2/settings/SettingsBuilder.java b/core/src/main/java/com/onelogin/saml2/settings/SettingsBuilder.java index e7b95ff0..c249416c 100644 --- a/core/src/main/java/com/onelogin/saml2/settings/SettingsBuilder.java +++ b/core/src/main/java/com/onelogin/saml2/settings/SettingsBuilder.java @@ -402,7 +402,7 @@ private void loadSecuritySetting() { Boolean wantDestinationUrlvalidation = loadBooleanProperty(SECURITY_WANT_DESTINATION_URL_VALIDATION); if (wantDestinationUrlvalidation != null) - saml2Setting.setDestinationUrlValidation(wantDestinationUrlvalidation); + saml2Setting.setWantDestinationUrlValidation(wantDestinationUrlvalidation); Boolean signMetadata = loadBooleanProperty(SECURITY_SIGN_METADATA); if (signMetadata != null) diff --git a/core/src/test/java/com/onelogin/saml2/test/authn/AuthnResponseTest.java b/core/src/test/java/com/onelogin/saml2/test/authn/AuthnResponseTest.java index 7632be9c..b3d4a62e 100644 --- a/core/src/test/java/com/onelogin/saml2/test/authn/AuthnResponseTest.java +++ b/core/src/test/java/com/onelogin/saml2/test/authn/AuthnResponseTest.java @@ -5,7 +5,6 @@ import com.onelogin.saml2.exception.SettingsException; import com.onelogin.saml2.exception.ValidationError; import com.onelogin.saml2.http.HttpRequest; -import com.onelogin.saml2.logout.LogoutRequest; import com.onelogin.saml2.model.SamlResponseStatus; import com.onelogin.saml2.settings.Saml2Settings; import com.onelogin.saml2.settings.SettingsBuilder; @@ -1947,7 +1946,7 @@ public void testIsInValidDestination() throws IOException, Error, XPathExpressio samlResponse.isValid(); assertThat(samlResponse.getError(), not(containsString("The response was received at"))); - settings.setDestinationUrlValidation(false); + settings.setWantDestinationUrlValidation(false); samlResponse = new SamlResponse(settings, newHttpRequest(requestURL, samlResponseEncoded)); samlResponse.isValid(); assertThat(samlResponse.getError(), not(containsString("The response was received at"))); diff --git a/core/src/test/java/com/onelogin/saml2/test/settings/Saml2SettingsTest.java b/core/src/test/java/com/onelogin/saml2/test/settings/Saml2SettingsTest.java index d45f0f6c..7b60b497 100644 --- a/core/src/test/java/com/onelogin/saml2/test/settings/Saml2SettingsTest.java +++ b/core/src/test/java/com/onelogin/saml2/test/settings/Saml2SettingsTest.java @@ -500,7 +500,7 @@ public void testIsWantDestinationUrlValidation() { Saml2Settings settings = new Saml2Settings(); assertTrue(settings.getWantDestinationUrlValidation()); - settings.setDestinationUrlValidation(false); + settings.setWantDestinationUrlValidation(false); assertFalse(settings.getWantDestinationUrlValidation()); } }