Skip to content

Commit

Permalink
fixes SAML-Toolkits#322: allow SAML responses without Conditions
Browse files Browse the repository at this point in the history
- the conditions element is optional according to the spec
- require Conditions element to be present by default
- added new configuration option to allow lack of Conditions
  • Loading branch information
ThePetrov committed Apr 2, 2021
1 parent 523786b commit f3c97a9
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 3 deletions.
6 changes: 4 additions & 2 deletions core/src/main/java/com/onelogin/saml2/authn/SamlResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,10 @@ public boolean isValid(String requestId) {
}

// Validate Conditions element exists
if (!this.checkOneCondition()) {
throw new ValidationError("The Assertion must include a Conditions element", ValidationError.MISSING_CONDITIONS);
if (settings.isWantConditionsPresent()) {
if (!this.checkOneCondition()) {
throw new ValidationError("The Assertion must include a Conditions element", ValidationError.MISSING_CONDITIONS);
}
}

// Validate Assertion timestamps
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public class Saml2Settings {
private boolean allowRepeatAttributeName = false;
private boolean rejectDeprecatedAlg = false;
private String uniqueIDPrefix = null;
private boolean wantConditionsPresent = true;

// Compress
private boolean compressRequest = true;
Expand Down Expand Up @@ -1052,7 +1053,25 @@ public boolean getSPValidationOnly()
{
return this.spValidationOnly;
}



/**
*
* @return the wantConditionsPresentValue
*/
public boolean isWantConditionsPresent() {
return wantConditionsPresent;
}

/**
* Set the wantConditionsPresent value, used to determine if the Conditions element is required
*
* @param wantConditionsPresent the wantConditionsPresent value
*/
public void setWantConditionsPresent(boolean wantConditionsPresent) {
this.wantConditionsPresent = wantConditionsPresent;
}

/**
* Gets the SP metadata. The XML representation.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ public class SettingsBuilder {
public final static String SECURITY_WANT_MESSAGES_SIGNED = "onelogin.saml2.security.want_messages_signed";
public final static String SECURITY_WANT_ASSERTIONS_SIGNED = "onelogin.saml2.security.want_assertions_signed";
public final static String SECURITY_WANT_ASSERTIONS_ENCRYPTED = "onelogin.saml2.security.want_assertions_encrypted";
public final static String SECURITY_WANT_CONDITIONS_PRESENT = "onelogin.saml2.security.want_conditions_present";
public final static String SECURITY_WANT_NAMEID = "onelogin.saml2.security.want_nameid";
public final static String SECURITY_WANT_NAMEID_ENCRYPTED = "onelogin.saml2.security.want_nameid_encrypted";
public final static String SECURITY_SIGN_METADATA = "onelogin.saml2.security.sign_metadata";
Expand Down Expand Up @@ -373,6 +374,10 @@ private void loadSecuritySetting() {
if (wantXMLValidation != null)
saml2Setting.setWantXMLValidation(wantXMLValidation);

Boolean wantConditionsPresent = loadBooleanProperty(SECURITY_WANT_CONDITIONS_PRESENT);
if (wantConditionsPresent != null)
saml2Setting.setWantConditionsPresent(wantConditionsPresent);

Boolean signMetadata = loadBooleanProperty(SECURITY_SIGN_METADATA);
if (signMetadata != null)
saml2Setting.setSignMetadata(signMetadata);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1697,6 +1697,31 @@ public void testIsInValidConditions() throws IOException, Error, XPathExpression
assertEquals("The Assertion must include a Conditions element", samlResponse.getError());
}

/**
* Tests the isValid method of SamlResponse
* Case: invalid Conditions
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsInValidConditionsWithoutConditionsValidation() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.mywithoutconditions.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_conditions.xml.base64");
setDateTime("2014-02-19T09:35:01Z");

SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest("https://example.com/newonelogin/demo1/index.php?acs", samlResponseEncoded));
assertTrue(samlResponse.isValid());
assertNull(samlResponse.getError());
}

/**
* Tests the isValid method of SamlResponse
* Case: invalid Conditions
Expand Down
145 changes: 145 additions & 0 deletions core/src/test/resources/config/config.mywithoutconditions.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# If 'strict' is True, then the Java Toolkit will reject unsigned
# or unencrypted messages if it expects them signed or encrypted
# Also will reject the messages if not strictly follow the SAML
onelogin.saml2.strict = true

# Enable debug mode (to print errors)
onelogin.saml2.debug = true

# Service Provider Data that we are deploying
# Identifier of the SP entity (must be a URI)
onelogin.saml2.sp.entityid = http://localhost:8080/java-saml-jspsample/metadata.jsp
# Specifies info about where and how the <AuthnResponse> message MUST be
# returned to the requester, in this case our SP.
# URL Location where the <Response> from the IdP will be returned
onelogin.saml2.sp.assertion_consumer_service.url = http://localhost:8080/java-saml-jspsample/acs.jsp
# SAML protocol binding to be used when returning the <Response> or sending the <LogoutRequest>
# message. Onelogin Toolkit supports for this endpoint the
# HTTP-POST binding only
onelogin.saml2.sp.assertion_consumer_service.binding = urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST

# Specifies info about Logout service
# URL Location where the <LogoutResponse> from the IdP will be returned or where to send the <LogoutRequest>
onelogin.saml2.sp.single_logout_service.url = http://localhost:8080/java-saml-jspsample/sls.jsp

# SAML protocol binding for the Single Logout Service of the SP.
# Onelogin Toolkit supports for this endpoint the HTTP-Redirect binding only
onelogin.saml2.sp.single_logout_service.binding = urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect

# Specifies constraints on the name identifier to be used to
# represent the requested subject.
# Take a look on lib/Saml2/Constants.php to see the NameIdFormat supported
onelogin.saml2.sp.nameidformat = urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified

# Usually x509cert and privateKey of the SP are provided by files placed at
# the certs folder. But we can also provide them with the following parameters
onelogin.saml2.sp.x509cert = -----BEGIN CERTIFICATE-----MIICgTCCAeoCCQCbOlrWDdX7FTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCTk8xGDAWBgNVBAgTD0FuZHJlYXMgU29sYmVyZzEMMAoGA1UEBxMDRm9vMRAwDgYDVQQKEwdVTklORVRUMRgwFgYDVQQDEw9mZWlkZS5lcmxhbmcubm8xITAfBgkqhkiG9w0BCQEWEmFuZHJlYXNAdW5pbmV0dC5ubzAeFw0wNzA2MTUxMjAxMzVaFw0wNzA4MTQxMjAxMzVaMIGEMQswCQYDVQQGEwJOTzEYMBYGA1UECBMPQW5kcmVhcyBTb2xiZXJnMQwwCgYDVQQHEwNGb28xEDAOBgNVBAoTB1VOSU5FVFQxGDAWBgNVBAMTD2ZlaWRlLmVybGFuZy5ubzEhMB8GCSqGSIb3DQEJARYSYW5kcmVhc0B1bmluZXR0Lm5vMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDivbhR7P516x/S3BqKxupQe0LONoliupiBOesCO3SHbDrl3+q9IbfnfmE04rNuMcPsIxB161TdDpIesLCn7c8aPHISKOtPlAeTZSnb8QAu7aRjZq3+PbrP5uW3TcfCGPtKTytHOge/OlJbo078dVhXQ14d1EDwXJW1rRXuUt4C8QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACDVfp86HObqY+e8BUoWQ9+VMQx1ASDohBjwOsg2WykUqRXF+dLfcUH9dWR63CtZIKFDbStNomPnQz7nbK+onygwBspVEbnHuUihZq3ZUdmumQqCw4Uvs/1Uvq3orOo/WJVhTyvLgFVK2QarQ4/67OZfHd7R+POBXhophSMv1ZOo-----END CERTIFICATE-----


# Requires Format PKCS#8 BEGIN PRIVATE KEY
# If you have PKCS#1 BEGIN RSA PRIVATE KEY convert it by openssl pkcs8 -topk8 -inform pem -nocrypt -in sp.rsa_key -outform pem -out sp.pem
onelogin.saml2.sp.privatekey = -----BEGIN PRIVATE KEY-----MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOK9uFHs/nXrH9LcGorG6lB7Qs42iWK6mIE56wI7dIdsOuXf6r0ht+d+YTTis24xw+wjEHXrVN0Okh6wsKftzxo8chIo60+UB5NlKdvxAC7tpGNmrf49us/m5bdNx8IY+0pPK0c6B786UlujTvx1WFdDXh3UQPBclbWtFe5S3gLxAgMBAAECgYAPj9ngtZVZXoPWowinUbOvRmZ1ZMTVI91nsSPyCUacLM92C4I+7NuEZeYiDRUnkP7TbCyrCzXN3jwlIxdczzORhlXBBgg9Sw2fkV61CnDEMgw+aEeD5A0GDA6eTwkrawiOMs8vupjsi2/stPsa+bmpI6RnfdEKBdyDP6iQQhAxiQJBAPNtM7IMvRzlZBXoDaTTpP9rN2FR0ZcX0LT5aRZJ81qi+ZOBFeHUb6MyWvzZKfPinj9JO3s/9e3JbMXemRWBmvcCQQDuc+NfAeW200QyjoC3Ed3jueLMrY1Q3zTcSUhRPw/0pIKgRGZJerro8N6QY2JziV2mxK855gKTwwBigMHL2S9XAkEAwuBfjGDqXOG/uFHn6laNNvWshjqsIdus99Tbrj5RlfP2/YFP9VTOcsXzVYy9K0P3EA8ekVLpHQ4uCFJmF3OEjQJBAMvwO69/HOufhv1CWZ25XzAsRGhPqsRXEouw9XPfXpMavEm8FkuT9xXRJFkTVxl/i6RdJYx8Rwn/Rm34t0bUKqMCQQCrAtKCUn0PLcemAzPi8ADJlbMDG/IDXNbSej0Y4tw9Cdho1Q38XLZJi0RNdNvQJD1fWu3x9+QU/vJr7lMLzdoy-----END PRIVATE KEY-----

# Identity Provider Data that we want connect with our SP
# Identifier of the IdP entity (must be a URI)
onelogin.saml2.idp.entityid = https://example.com/simplesaml/saml2/idp/metadata.php

# SSO endpoint info of the IdP. (Authentication Request protocol)
# URL Target of the IdP where the SP will send the Authentication Request Message
onelogin.saml2.idp.single_sign_on_service.url = https://pitbulk.no-ip.org/simplesaml/saml2/idp/SSOService.php

# SAML protocol binding to be used when returning the <Response>
# message. Onelogin Toolkit supports for this endpoint the
# HTTP-Redirect binding only
onelogin.saml2.idp.single_sign_on_service.binding = urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect

# SLO endpoint info of the IdP.
# URL Location of the IdP where the SP will send the SLO Request
onelogin.saml2.idp.single_logout_service.url = https://pitbulk.no-ip.org/simplesaml/saml2/idp/SingleLogoutService.php

# SAML protocol binding to be used when returning the <Response>
# message. Onelogin Toolkit supports for this endpoint the
# HTTP-Redirect binding only
onelogin.saml2.idp.single_logout_service.binding = urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect

# Public x509 certificate of the IdP
onelogin.saml2.idp.x509cert = -----BEGIN CERTIFICATE-----MIICgTCCAeoCCQCbOlrWDdX7FTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCTk8xGDAWBgNVBAgTD0FuZHJlYXMgU29sYmVyZzEMMAoGA1UEBxMDRm9vMRAwDgYDVQQKEwdVTklORVRUMRgwFgYDVQQDEw9mZWlkZS5lcmxhbmcubm8xITAfBgkqhkiG9w0BCQEWEmFuZHJlYXNAdW5pbmV0dC5ubzAeFw0wNzA2MTUxMjAxMzVaFw0wNzA4MTQxMjAxMzVaMIGEMQswCQYDVQQGEwJOTzEYMBYGA1UECBMPQW5kcmVhcyBTb2xiZXJnMQwwCgYDVQQHEwNGb28xEDAOBgNVBAoTB1VOSU5FVFQxGDAWBgNVBAMTD2ZlaWRlLmVybGFuZy5ubzEhMB8GCSqGSIb3DQEJARYSYW5kcmVhc0B1bmluZXR0Lm5vMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDivbhR7P516x/S3BqKxupQe0LONoliupiBOesCO3SHbDrl3+q9IbfnfmE04rNuMcPsIxB161TdDpIesLCn7c8aPHISKOtPlAeTZSnb8QAu7aRjZq3+PbrP5uW3TcfCGPtKTytHOge/OlJbo078dVhXQ14d1EDwXJW1rRXuUt4C8QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACDVfp86HObqY+e8BUoWQ9+VMQx1ASDohBjwOsg2WykUqRXF+dLfcUH9dWR63CtZIKFDbStNomPnQz7nbK+onygwBspVEbnHuUihZq3ZUdmumQqCw4Uvs/1Uvq3orOo/WJVhTyvLgFVK2QarQ4/67OZfHd7R+POBXhophSMv1ZOo-----END CERTIFICATE-----

# Security settings
#

# Indicates that the nameID of the <samlp:logoutRequest> sent by this SP
# will be encrypted.
onelogin.saml2.security.nameid_encrypted = true

# Indicates whether the <samlp:AuthnRequest> messages sent by this SP
# will be signed. [The Metadata of the SP will offer this info]
onelogin.saml2.security.authnrequest_signed = true

# Indicates whether the <samlp:logoutRequest> messages sent by this SP
# will be signed.
onelogin.saml2.security.logoutrequest_signed = true

# Indicates whether the <samlp:logoutResponse> messages sent by this SP
# will be signed.
onelogin.saml2.security.logoutresponse_signed = true

# Indicates a requirement for the <samlp:Response>, <samlp:LogoutRequest> and
# <samlp:LogoutResponse> elements received by this SP to be signed.
onelogin.saml2.security.want_messages_signed = false

# Indicates a requirement for the <saml:Assertion> of the <samlp:Response> to be signed
onelogin.saml2.security.want_assertions_signed = true

# Indicates a requirement for the Metadata of this SP to be signed.
# Right now supported null/false (in order to not sign) or true (sign using SP private key)
onelogin.saml2.security.sign_metadata = true

# Indicates a requirement for the Assertions received by this SP to be encrypted
onelogin.saml2.security.want_assertions_encrypted = false

# Indicates a requirement for the NameID received by this SP to be encrypted
onelogin.saml2.security.want_nameid = true

# Indicates a requirement for the NameID received by this SP to be encrypted
onelogin.saml2.security.want_nameid_encrypted = false

# Authentication context.
# Set Empty and no AuthContext will be sent in the AuthNRequest,
# Set comma separated values urn:oasis:names:tc:SAML:2.0:ac:classes:urn:oasis:names:tc:SAML:2.0:ac:classes:Password
onelogin.saml2.security.requested_authncontext = urn:oasis:names:tc:SAML:2.0:ac:classes:urn:oasis:names:tc:SAML:2.0:ac:classes:Password

# Allows the authn comparison parameter to be set, defaults to 'exact'
onelogin.saml2.security.requested_authncontextcomparison = exact

onelogin.saml2.security.want_conditions_present = false


# Indicates if the SP will validate all received xmls.
# (In order to validate the xml, 'strict' and 'wantXMLValidation' must be true).
onelogin.saml2.security.want_xml_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/2001/04/xmldsig-more#rsa-sha256'
# 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384'
# 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512'
onelogin.saml2.security.signature_algorithm = http://www.w3.org/2001/04/xmldsig-more#rsa-sha512

# Algorithm that the toolkit will use on digest process. Options:
# 'http://www.w3.org/2000/09/xmldsig#sha1'
# 'http://www.w3.org/2001/04/xmlenc#sha256'
# 'http://www.w3.org/2001/04/xmldsig-more#sha384'
# 'http://www.w3.org/2001/04/xmlenc#sha512'
onelogin.saml2.security.digest_algorithm = http://www.w3.org/2001/04/xmlenc#sha512

# Organization
onelogin.saml2.organization.name = SP Java
onelogin.saml2.organization.displayname = SP Java Example
onelogin.saml2.organization.url = http://sp.example.com

# Contacts
onelogin.saml2.contacts.technical.given_name = Technical Guy
onelogin.saml2.contacts.technical.email_address = [email protected]
onelogin.saml2.contacts.support.given_name = Support Guy
onelogin.saml2.contacts.support.email_address = [email protected]

0 comments on commit f3c97a9

Please sign in to comment.