package com.onelogin.saml2.test.authn;
import com.onelogin.saml2.authn.SamlResponse;
import com.onelogin.saml2.exception.Error;
import com.onelogin.saml2.exception.SettingsException;
import com.onelogin.saml2.exception.ValidationError;
import com.onelogin.saml2.http.HttpRequest;
import com.onelogin.saml2.model.SamlResponseStatus;
import com.onelogin.saml2.settings.Saml2Settings;
import com.onelogin.saml2.settings.SettingsBuilder;
import com.onelogin.saml2.util.Constants;
import com.onelogin.saml2.util.Util;
import org.hamcrest.Matchers;
import org.joda.time.Instant;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
public class AuthnResponseTest {
private static final String ACS_URL = "http://localhost:8080/java-saml-jspsample/acs.jsp";
@Rule
public ExpectedException expectedEx = ExpectedException.none();
/**
* Tests the constructor of SamlResponse
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse
*/
@Test
public void testConstructor() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
final String requestURL = "/";
String samlResponseEncoded = Util.getFileAsString("data/responses/response1.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(requestURL, samlResponseEncoded));
assertTrue(samlResponse instanceof SamlResponse);
samlResponseEncoded = Util.getFileAsString("data/responses/valid_encrypted_assertion.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(requestURL, samlResponseEncoded));
assertTrue(samlResponse instanceof SamlResponse);
}
/**
* Tests the constructor of SamlResponse
* Case: Encrypted assertion but no key
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#getNameId
*/
@Test
public void testEncryptedAssertionNokey() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
expectedEx.expect(SettingsException.class);
expectedEx.expectMessage("No private key available for decrypt, check settings");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/valid_encrypted_assertion.xml.base64");
new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
}
/**
* Tests the constructor of SamlResponse
* Case test namespaces
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse
*/
@Test
public void testNamespaces() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/open_saml_response.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
HashMap<String, List<String>> attributes = samlResponse.getAttributes();
assertFalse(attributes.isEmpty());
assertTrue(attributes.containsKey("FirstName"));
assertTrue(attributes.containsKey("LastName"));
List<String> expectedFirstName = new ArrayList<String>();
expectedFirstName.add("Someone");
List<String> expectedLastName = new ArrayList<String>();
expectedLastName.add("Special");
assertEquals(expectedFirstName, attributes.get("FirstName"));
assertEquals(expectedLastName, attributes.get("LastName"));
}
/**
* Tests the getSAMLResponseXml method of SamlResponse
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#getSAMLResponseXml
*/
@Test
public void testGetSAMLResponseXml() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
final String requestURL = "/";
String samlResponseEncoded = Util.getFileAsString("data/responses/response1.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(requestURL, samlResponseEncoded));
String samlResponseXML = samlResponse.getSAMLResponseXml();
assertThat(samlResponseXML, containsString("<samlp:Response"));
samlResponseEncoded = Util.getFileAsString("data/responses/valid_encrypted_assertion.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(requestURL, samlResponseEncoded));
samlResponseXML = samlResponse.getSAMLResponseXml();
assertThat(samlResponseXML, containsString("<samlp:Response"));
assertThat(samlResponseXML, containsString("<saml:Assertion"));
}
/**
* Tests the getNameId method of SamlResponse
*
* @throws Exception
*
* @see com.onelogin.saml2.authn.SamlResponse#getNameId
*/
@Test
public void testGetNameId() throws Exception {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/response1.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals("support@onelogin.com", samlResponse.getNameId());
samlResponseEncoded = Util.getFileAsString("data/responses/response_encrypted_nameid.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals("2de11defd199f8d5bb63f9b7deb265ba5c675c10", samlResponse.getNameId());
samlResponseEncoded = Util.getFileAsString("data/responses/valid_encrypted_assertion.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals("_68392312d490db6d355555cfbbd8ec95d746516f60", samlResponse.getNameId());
settings.setWantNameId(false);
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_nameid.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertNull(samlResponse.getNameId());
}
/**
* Tests the getNameIdFormat method of SamlResponse
*
* @throws Exception
*
* @see com.onelogin.saml2.authn.SamlResponse#getNameIdFormat
*/
@Test
public void testGetNameIdFormat() throws Exception {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/response1.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals("urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", samlResponse.getNameIdFormat());
samlResponseEncoded = Util.getFileAsString("data/responses/response_encrypted_nameid.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals("urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified", samlResponse.getNameIdFormat());
samlResponseEncoded = Util.getFileAsString("data/responses/valid_encrypted_assertion.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals("urn:oasis:names:tc:SAML:2.0:nameid-format:transient", samlResponse.getNameIdFormat());
settings.setWantNameId(false);
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_nameid.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertNull(samlResponse.getNameIdFormat());
}
/**
* Tests the getNameId method of SamlResponse
* Case: No NameId
*
* @throws Exception
*
* @see com.onelogin.saml2.authn.SamlResponse#getNameId
*/
@Test
public void testGetNameIdNoNameId() throws Exception {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("No name id found in Document.");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
settings.setWantNameId(true);
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_nameid.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
String nameId = samlResponse.getNameId();
}
/**
* Tests the getNameId method of SamlResponse
* Case: Wrong SPNameQualifier
*
* @throws Exception
*
* @see com.onelogin.saml2.authn.SamlResponse#getNameId
*/
@Test
public void testGetNameIdWrongSPNameQualifier() throws Exception {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("The SPNameQualifier value mistmatch the SP entityID value.");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
settings.setWantNameId(true);
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/wrong_spnamequalifier.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
String nameId = samlResponse.getNameId();
}
/**
* Tests the getNameId method of SamlResponse
* Case: Not able to get the NameIdData due no private key to decrypt
*
* @throws Exception
*
* @see com.onelogin.saml2.authn.SamlResponse#getNameId
*/
@Test
public void testGetNameIdNoKey() throws Exception {
expectedEx.expect(SettingsException.class);
expectedEx.expectMessage("Key is required in order to decrypt the NameID");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/response_encrypted_nameid.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
String nameId = samlResponse.getNameId();
}
/**
* Tests the getNameId method of SamlResponse
* Case: The NameID value is empty
*
* @throws Exception
*
* @see com.onelogin.saml2.authn.SamlResponse#getNameId
*/
@Test
public void testGetNameIdEmptyNameIDValue() throws Exception {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("An empty NameID value found");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/empty_nameid.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
String nameId = samlResponse.getNameId();
assertTrue(nameId.isEmpty());
settings.setStrict(true);
SamlResponse samlResponse2 = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
String nameId2 = samlResponse2.getNameId();
}
/**
* Tests the getNameId method of SamlResponse
* Case: Not able to get the NameIdData due no nameID inside the EncryptedID
*
* @throws Exception
*
* @see com.onelogin.saml2.authn.SamlResponse#getNameId
*/
@Test
public void testGetNameIdWrongEncryptedData() throws Exception {
expectedEx.expect(Exception.class);
expectedEx.expectMessage("Not able to decrypt the EncryptedID and get a NameID");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/response_encrypted_subconfirm_as_nameid.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
String nameId = samlResponse.getNameId();
}
/**
* Tests the getNameIdData method of SamlResponse
*
* @throws Exception
*
* @see com.onelogin.saml2.authn.SamlResponse#getNameIdData
*/
@Test
public void testGetNameIdData() throws Exception {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/response1.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals("{Format=urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress, Value=support@onelogin.com}", samlResponse.getNameIdData().toString());
samlResponseEncoded = Util.getFileAsString("data/responses/response_encrypted_nameid.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
String NameIdDataStr = samlResponse.getNameIdData().toString();
assertThat(NameIdDataStr, containsString("Format=urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"));
assertThat(NameIdDataStr, containsString("Value=2de11defd199f8d5bb63f9b7deb265ba5c675c10"));
assertThat(NameIdDataStr, containsString("SPNameQualifier=http://localhost:8080/java-saml-jspsample/metadata.jsp"));
samlResponseEncoded = Util.getFileAsString("data/responses/valid_encrypted_assertion.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
NameIdDataStr = samlResponse.getNameIdData().toString();
assertThat(NameIdDataStr, containsString("Format=urn:oasis:names:tc:SAML:2.0:nameid-format:transient"));
assertThat(NameIdDataStr, containsString("Value=_68392312d490db6d355555cfbbd8ec95d746516f60"));
assertThat(NameIdDataStr, containsString("SPNameQualifier=http://localhost:8080/java-saml-jspsample/metadata.jsp"));
settings.setWantNameId(false);
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_nameid.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.getNameIdData().isEmpty());
}
/**
* Tests the decryptAssertion method of SamlResponse
* Case: EncryptedAssertion with an encryptedData element with a KeyInfo
* that contains a RetrievalMethod to obtain the EncryptedKey.
*
* @throws Exception
*/
@Test
public void testEncryptedResponse() throws Exception {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.decrypt.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/response_to_decrypt.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals("archit.neema@intellicus.com", samlResponse.getNameId());
}
/**
* Tests the getNameIdData method of SamlResponse
* Case: No NameId
*
* @throws Exception
*
* @see com.onelogin.saml2.authn.SamlResponse#getNameIdData
*/
@Test
public void testGetNameIdDataNoNameId() throws Exception {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("No name id found in Document");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
settings.setWantNameId(true);
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_nameid.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
HashMap<String, String> nameIdData = samlResponse.getNameIdData();
}
/**
* Tests the getNameIdData method of SamlResponse
* Case: Wrong SPNameQualifier
*
* @throws Exception
*
* @see com.onelogin.saml2.authn.SamlResponse#getNameIdData
*/
@Test
public void testGetNameIdDataWrongSPNameQualifier() throws Exception {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("The SPNameQualifier value mistmatch the SP entityID value.");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
settings.setWantNameId(true);
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/wrong_spnamequalifier.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
HashMap<String, String> nameIdData = samlResponse.getNameIdData();
}
/**
* Tests the getNameIdData method of SamlResponse
* Case: The NameID value is empty
*
* @throws Exception
*
* @see com.onelogin.saml2.authn.SamlResponse#getNameIdData
*/
@Test
public void testGetNameIdDataEmptyNameIDValue() throws Exception {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("An empty NameID value found");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/empty_nameid.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
HashMap<String, String> nameIdData = samlResponse.getNameIdData();
assertTrue(nameIdData.get("Value").isEmpty());
settings.setStrict(true);
SamlResponse samlResponse2 = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
HashMap<String, String> nameIdData2 = samlResponse2.getNameIdData();
}
/**
* Tests the checkOneCondition method of SamlResponse
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#checkOneCondition
*/
@Test
public void checkOneCondition() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_conditions.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.checkOneCondition());
samlResponseEncoded = Util.getFileAsString("data/responses/valid_response.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.checkOneCondition());
}
/**
* Tests the checkOneAuthnStatement method of SamlResponse
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#checkOneAuthnStatement
*/
@Test
public void checkOneAuthNStatement() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_authnstatement.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.checkOneAuthnStatement());
samlResponseEncoded = Util.getFileAsString("data/responses/valid_response.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.checkOneAuthnStatement());
}
/**
* Tests the checkStatus method of SamlResponse
* Case Status = Success
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#checkStatus
*/
@Test
public void testCheckStatus() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/response1.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
samlResponse.checkStatus();
samlResponseEncoded = Util.getFileAsString("data/responses/valid_encrypted_assertion.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
samlResponse.checkStatus();
}
/**
* Tests the checkStatus method of SamlResponse
* Case Status = Responder
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#checkStatus
*/
@Test
public void testCheckStatusResponder() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("The status code of the Response was not Success, was urn:oasis:names:tc:SAML:2.0:status:Responder");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/status_code_responder.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
samlResponse.checkStatus();
}
/**
* Tests the checkStatus method of SamlResponse
* Case Status = Responder + Msg
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#checkStatus
*/
@Test
public void testCheckStatusResponderMsg() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("The status code of the Response was not Success, was urn:oasis:names:tc:SAML:2.0:status:Responder -> something_is_wrong");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/status_code_responder_and_msg.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
samlResponse.checkStatus();
}
/**
* Tests the checkStatus method of SamlResponse
* Case No Status
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#checkStatus
*/
@Test
public void testCheckStatusNoStatus() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("Missing Status on response");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_status.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
samlResponse.checkStatus();
}
/**
* Tests the checkStatus method of SamlResponse
* Case No StatusCode
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#checkStatus
*/
@Test
public void testCheckStatusNoStatusCode() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("Missing Status Code on response");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_status_code.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
samlResponse.checkStatus();
}
/**
* Tests the getStatus method of SamlResponse
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#getStatus
*/
@Test
public void testGetStatus() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
String samlResponseEncoded = Util.getFileAsString("data/responses/response1.xml.base64");
Document samlResponseDoc = Util.loadXML(new String(Util.base64decoder(samlResponseEncoded)));
SamlResponseStatus status = SamlResponse.getStatus(samlResponseDoc);
assertEquals(Constants.STATUS_SUCCESS, status.getStatusCode());
assertNull(status.getStatusMessage());
samlResponseEncoded = Util.getFileAsString("data/responses/valid_encrypted_assertion.xml.base64");
samlResponseDoc = Util.loadXML(new String(Util.base64decoder(samlResponseEncoded)));
status = SamlResponse.getStatus(samlResponseDoc);
assertEquals(Constants.STATUS_SUCCESS, status.getStatusCode());
assertNull(status.getStatusMessage());
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/status_code_responder.xml.base64");
samlResponseDoc = Util.loadXML(new String(Util.base64decoder(samlResponseEncoded)));
status = SamlResponse.getStatus(samlResponseDoc);
assertEquals(Constants.STATUS_RESPONDER, status.getStatusCode());
assertNull(status.getStatusMessage());
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/status_code_responder_and_msg.xml.base64");
samlResponseDoc = Util.loadXML(new String(Util.base64decoder(samlResponseEncoded)));
status = SamlResponse.getStatus(samlResponseDoc);
assertEquals(Constants.STATUS_RESPONDER, status.getStatusCode());
assertEquals("something_is_wrong", status.getStatusMessage());
}
/**
* Tests the getAudiences method of SamlResponse
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#getAudiences
*/
@Test
public void testGetAudiences() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/response1.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
List<String> expectedAudiences = new ArrayList<String>();
expectedAudiences.add("{audience}");
assertEquals(expectedAudiences, samlResponse.getAudiences());
samlResponseEncoded = Util.getFileAsString("data/responses/valid_encrypted_assertion.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
expectedAudiences = new ArrayList<String>();
expectedAudiences.add("http://localhost:8080/java-saml-jspsample/metadata.jsp");
assertEquals(expectedAudiences, samlResponse.getAudiences());
}
/**
* Tests the getIssuers method of SamlResponse
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#getIssuers
*/
@Test
public void testGetIssuers() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/response1.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
List<String> expectedIssuers = new ArrayList<String>();
expectedIssuers.add("http://idp.example.com/");
samlResponseEncoded = Util.getFileAsString("data/responses/valid_encrypted_assertion.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals(expectedIssuers, samlResponse.getIssuers());
expectedIssuers.remove(0);
expectedIssuers.add("https://pitbulk.no-ip.org/simplesaml/saml2/idp/metadata.php");
samlResponseEncoded = Util.getFileAsString("data/responses/signed_message_encrypted_assertion.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals(expectedIssuers, samlResponse.getIssuers());
samlResponseEncoded = Util.getFileAsString("data/responses/double_signed_encrypted_assertion.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals(expectedIssuers, samlResponse.getIssuers());
samlResponseEncoded = Util.getFileAsString("data/responses/signed_encrypted_assertion.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals(expectedIssuers, samlResponse.getIssuers());
samlResponseEncoded = Util.getFileAsString("data/responses/double_signed_response.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals(expectedIssuers, samlResponse.getIssuers());
samlResponseEncoded = Util.getFileAsString("data/responses/signed_assertion_response.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals(expectedIssuers, samlResponse.getIssuers());
expectedIssuers = new ArrayList<String>();
expectedIssuers.add("https://app.onelogin.com/saml/metadata/13590");
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_issuer_response.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals(expectedIssuers, samlResponse.getIssuers());
}
/**
* Tests the getIssuers method of SamlResponse
* Case: Issuer of the assertion not found
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#getIssuers
*/
@Test
public void testGetIssuersNoInAssertion() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("Issuer of the Assertion not found or multiple.");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_issuer_assertion.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
List<String> issuers = samlResponse.getIssuers();
}
/**
* Tests the getSessionIndex method of SamlResponse
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#getSessionIndex
*/
@Test
public void testGetSessionIndex() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/response1.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals("_531c32d283bdff7e04e487bcdbc4dd8d", samlResponse.getSessionIndex());
samlResponseEncoded = Util.getFileAsString("data/responses/valid_encrypted_assertion.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals("_7164a9a9f97828bfdb8d0ebc004a05d2e7d873f70c", samlResponse.getSessionIndex());
}
@Test
public void testGetAssertionDetails() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
final SamlResponse samlResponse = new SamlResponse(
new SettingsBuilder().fromFile("config/config.my.properties").build(),
newHttpRequest(Util.getFileAsString("data/responses/response1.xml.base64"))
);
final List<Instant> notOnOrAfters = samlResponse.getAssertionNotOnOrAfter();
assertEquals("pfxa46574df-b3b0-a06a-23c8-636413198772", samlResponse.getAssertionId());
assertThat(notOnOrAfters, contains(new Instant("2010-11-18T22:02:37Z")));
}
@Test
public void testGetAssertionDetails_encrypted() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
final SamlResponse samlResponse = new SamlResponse(
new SettingsBuilder().fromFile("config/config.my.properties").build(),
newHttpRequest(Util.getFileAsString("data/responses/valid_encrypted_assertion.xml.base64"))
);
final List<Instant> notOnOrAfters = samlResponse.getAssertionNotOnOrAfter();
assertEquals("_519c2712648ee09a06d1f9a08e9e835715fea60267", samlResponse.getAssertionId());
assertThat(notOnOrAfters, contains(new Instant("2055-06-07T20:17:08Z")));
}
@Test
public void testGetAssertionDetails_multiple() throws Exception {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
settings.setWantAssertionsSigned(false);
settings.setWantMessagesSigned(true);
final SamlResponse samlResponse = new SamlResponse(
settings,
newHttpRequest(loadSignMessageAndEncode("data/responses/invalids/invalid_subjectconfirmation_multiple_issues.xml"))
);
final List<Instant> notOnOrAfters = samlResponse.getAssertionNotOnOrAfter();
assertEquals("pfx7841991c-c73f-4035-e2ee-c170c0e1d3e4", samlResponse.getAssertionId());
assertThat(notOnOrAfters, contains(new Instant("2120-06-17T14:53:44Z"), new Instant("2010-06-17T14:53:44Z")));
}
/**
* Tests the getAttributes method of SamlResponse
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#getAttributes
*/
@Test
public void testGetAttributes() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/response1.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
HashMap<String, List<String>> expectedAttributes = new HashMap<String, List<String>>();
List<String> attrValues = new ArrayList<String>();
attrValues.add("demo");
List<String> attrValues2 = new ArrayList<String>();
attrValues2.add("value");
expectedAttributes.put("uid", attrValues);
expectedAttributes.put("another_value", attrValues2);
assertEquals(expectedAttributes, samlResponse.getAttributes());
samlResponseEncoded = Util.getFileAsString("data/responses/response2.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.getAttributes().isEmpty());
// Encrypted Attributes are not supported
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/encrypted_attrs.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.getAttributes().isEmpty());
}
/**
* Tests the getAttributes method of SamlResponse
* Case: Duplicated names
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#getAttributes
*/
@Test
public void testGetAttributesDuplicatedNames() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("Found an Attribute element with duplicated Name");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/duplicated_attributes.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
HashMap<String, List<String>> attributes = samlResponse.getAttributes();
}
/**
* Tests the isValid method of SamlResponse
*
* @throws Exception
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testOnlyRetrieveAssertionWithIDThatMatchesSignatureReference() throws Exception {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("SAML Response could not be processed");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/wrapped_response_2.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
String nameID = samlResponse.getNameId();
assertFalse(samlResponse.isValid());
assertFalse("root@example.com".equals(nameID));
}
/**
* Tests the isValid method of SamlResponse
*
* @throws Exception
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testDoesNotAllowSignatureWrappingAttack() throws Exception {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/response4.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals("test@onelogin.com", samlResponse.getNameId());
assertFalse(samlResponse.isValid());
assertEquals("SAML Response must contain 1 Assertion.", samlResponse.getError());
}
/**
* Tests the isValid method of SamlResponse
*
* @throws Exception
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testDoesNotAllowSignatureWrappingAttack2() throws Exception {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.newattack.properties").build();
String samlResponseEncoded = Util.base64encoder(Util.getFileAsString("data/responses/invalids/attacks/encrypted_new_attack.xml"));
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("Found an invalid Signed Element. SAML Response rejected", samlResponse.getError());
}
/**
* Tests the isValid method of SamlResponse
* Case: signature wrapping attack - doubled SAML response body
*
* @throws Exception
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testDoesNotAllowSignatureWrappingAttack3() throws Exception {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.newattack2.properties").build();
settings.setStrict(false);
final String requestURL = "https://example.com/endpoint";
String samlResponseEncoded = Util.base64encoder(Util.getFileAsString("data/responses/invalids/attacks/response_with_doubled_signed_assertion.xml"));
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(requestURL, samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("SAML Response must contain 1 Assertion.", samlResponse.getError());
// should expose only the signed data
assertEquals("someone@example.org", samlResponse.getNameId());
}
/**
* Tests the isValid method of SamlResponse
* Case: signature wrapping attack - concealed SAML response body
*
* @throws Exception
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testDoesNotAllowSignatureWrappingAttack4() throws Exception {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.newattack2.properties").build();
settings.setStrict(false);
final String requestURL = "https://example.com/endpoint";
String samlResponseEncoded = Util.base64encoder(Util.getFileAsString("data/responses/invalids/attacks/response_with_concealed_signed_assertion.xml"));
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(requestURL, samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("SAML Response must contain 1 Assertion.", samlResponse.getError());
// should expose only the signed data
assertEquals("someone@example.org", samlResponse.getNameId());
}
@Test
public void testValidatesTheExpectedSignatures() throws Exception {
// having
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
settings.setWantAssertionsSigned(true);
settings.setWantMessagesSigned(true);
String samlResponseEncoded = Util.base64encoder(Util.getFileAsString("data/responses/invalids/attacks/response_with_spoofed_response_signature.xml"));
// when
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
// then
assertFalse(samlResponse.isValid());
assertEquals("Invalid Signature Element {urn:oasis:names:tc:SAML:2.0:assertion}Response SAML Response rejected", samlResponse.getError());
}
/**
* Tests the getSessionNotOnOrAfter method of SamlResponse
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#getSessionNotOnOrAfter
*/
@Test
public void testGetSessionNotOnOrAfter() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/response1.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals(1290203857000L, samlResponse.getSessionNotOnOrAfter().getMillis());
samlResponseEncoded = Util.getFileAsString("data/responses/response2.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertNull(samlResponse.getSessionNotOnOrAfter());
samlResponseEncoded = Util.getFileAsString("data/responses/valid_encrypted_assertion.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals(2696012228000L, samlResponse.getSessionNotOnOrAfter().getMillis());
}
/**
* Tests the validateNumAssertions method of SamlResponse
*
* @throws ValidationError
* @throws IOException
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#validateNumAssertions
*/
@Test
public void testValidateNumAssertions() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/response1.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.validateNumAssertions());
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/multiple_assertions.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.validateNumAssertions());
}
/**
* Tests the validateTimestamps method of SamlResponse
*
* @throws ValidationError
* @throws IOException
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#validateTimestamps
*/
@Test
public void testValidateTimestamps() throws ValidationError, IOException, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, Error {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/valid_response.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.validateTimestamps());
samlResponseEncoded = Util.getFileAsString("data/responses/valid_encrypted_assertion.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.validateTimestamps());
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_time_condition.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.validateTimestamps());
}
/**
* Tests the validateTimestamps method of SamlResponse
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#validateTimestamps
*/
@Test
public void testValidateTimestampsExpired() throws ValidationError, XPathExpressionException, ParserConfigurationException, SAXException, IOException, SettingsException, Error {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("Could not validate timestamp: expired. Check system clock.");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/expired_response.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
samlResponse.validateTimestamps();
}
/**
* Tests the validateTimestamps method of SamlResponse
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#validateTimestamps
*/
@Test
public void testValidateTimestampsNA() throws ValidationError, XPathExpressionException, ParserConfigurationException, SAXException, IOException, SettingsException, Error {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("Could not validate timestamp: expired. Check system clock.");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/not_after_failed.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
samlResponse.validateTimestamps();
}
/**
* Tests the validateTimestamps method of SamlResponse
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#validateTimestamps
*/
@Test
public void testValidateTimestampsNB() throws ValidationError, XPathExpressionException, ParserConfigurationException, SAXException, IOException, SettingsException, Error {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("Could not validate timestamp: not yet valid. Check system clock.");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/not_before_failed.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
samlResponse.validateTimestamps();
}
/**
* Tests the isValid method of SamlResponse
* Case: null HttpServletRequest provided
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testNullRequest() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
SamlResponse samlResponse = new SamlResponse(settings, null);
assertFalse(samlResponse.isValid());
assertEquals("SAML Response is not loaded", samlResponse.getError());
}
/**
* Tests the isValid method of SamlResponse
* Case: null HttpServletRequest provided
*
* @throws IOException
* @throws Error
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testNoCurrentURL() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
final String requestURL = "";
String samlResponseEncoded = Util.getFileAsString("data/responses/valid_response.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(requestURL, samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("The URL of the current host was not established", samlResponse.getError());
samlResponse.setDestinationUrl(null);
assertFalse(samlResponse.isValid());
assertEquals("The URL of the current host was not established", samlResponse.getError());
}
/**
* Tests the isValid method of SamlResponse
* Case: invalid version
*
* @throws IOException
* @throws Error
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testValidateVersion() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_saml2.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("Unsupported SAML Version.", samlResponse.getError());
}
/**
* Tests the isValid method of SamlResponse
* Case: invalid ID
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testValidateID() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_id.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("Missing ID attribute on SAML Response.", samlResponse.getError());
}
/**
* Tests the isValid method of SamlResponse
* Case: expired response
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsInValidExpired() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/expired_response.xml.base64");
settings.setStrict(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.isValid());
settings.setStrict(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("Could not validate timestamp: expired. Check system clock.", samlResponse.getError());
}
/**
* Tests the isValid method of SamlResponse
* Case: no Key
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsInValidNoKey() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_key.xml.base64");
settings.setStrict(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("Signature validation failed. SAML Response rejected", samlResponse.getError());
}
/**
* Tests the isValid method of SamlResponse
* Case: invalid multiple assertions
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsInValidMultipleAssertions() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/multiple_assertions.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("SAML Response must contain 1 Assertion.", samlResponse.getError());
}
/**
* Tests the isValid method of SamlResponse
* Case: invalid Encrypted Attrs
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsInValidEncAttrs() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/encrypted_attrs.xml.base64");
settings.setStrict(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
settings.setStrict(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("There is an EncryptedAttribute in the Response and this SP not support them", samlResponse.getError());
}
/**
* Tests the isValid method of SamlResponse
* Case: valid but contained wrong NameId
*
* @throws Exception
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsValidWrongEncryptedID() throws Exception {
expectedEx.expect(Exception.class);
expectedEx.expectMessage("Not able to decrypt the EncryptedID and get a NameID");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/response_encrypted_subconfirm_as_nameid.xml.base64");
settings.setStrict(false);
settings.setWantAssertionsSigned(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.isValid());
String nameId = samlResponse.getNameId();
}
/**
* Tests the isValid method of SamlResponse
* Case: valid but contained wrong NameId
*
* @throws Exception
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsValidWrongSPNameQualifier() throws Exception {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("The SPNameQualifier value mistmatch the SP entityID value.");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/wrong_spnamequalifier.xml.base64");
settings.setStrict(true);
settings.setWantAssertionsSigned(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
String nameId = samlResponse.getNameId();
}
/**
* Tests the isValid method of SamlResponse
* Case: invalid xml
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsInValidWrongXML() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
final String requestURL = "https://pitbulk.no-ip.org/newonelogin/demo1/index.php?acs";
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/invalid_xml.xml.base64");
settings.setStrict(false);
settings.setWantXMLValidation(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(requestURL, samlResponseEncoded));
assertTrue(samlResponse.isValid());
settings.setWantXMLValidation(true);
samlResponse = new SamlResponse(settings, newHttpRequest(requestURL, samlResponseEncoded));
assertTrue(samlResponse.isValid());
settings.setStrict(true);
settings.setWantXMLValidation(false);
samlResponse = new SamlResponse(settings, newHttpRequest(requestURL, samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("http://localhost:8080/java-saml-jspsample/metadata.jsp is not a valid audience for this Response", samlResponse.getError());
settings.setWantXMLValidation(true);
samlResponse = new SamlResponse(settings, newHttpRequest(requestURL, samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("Invalid SAML Response. Not match the saml-schema-protocol-2.0.xsd", samlResponse.getError());
}
/**
* Tests the isValid method of SamlResponse
* Case: invalid Destination
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsInValidDestination() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
final String requestURL = "/";
String samlResponseEncoded = Util.getFileAsString("data/responses/unsigned_response.xml.base64");
settings.setStrict(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(requestURL, samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
settings.setStrict(true);
samlResponse = new SamlResponse(settings, newHttpRequest(requestURL, samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertThat(samlResponse.getError(), containsString("The response was received at"));
samlResponse.setDestinationUrl(ACS_URL);
samlResponse.isValid();
assertThat(samlResponse.getError(), not(containsString("The response was received at")));
}
/**
* Tests the isValid method of SamlResponse
* Case: No Destination
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsInValidNoDestination() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
final String requestURL = "/";
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/empty_destination.xml.base64");
settings.setStrict(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(requestURL, samlResponseEncoded));
assertTrue(samlResponse.isValid());
settings.setStrict(true);
samlResponse = new SamlResponse(settings, newHttpRequest(requestURL, samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("The response has an empty Destination value", 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 testIsInValidConditions() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_conditions.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
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 testIsInValidAuthStatement() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_authnstatement.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("The Assertion must include an AuthnStatement element", samlResponse.getError());
}
/**
* Tests the isValid method of SamlResponse
* Case: invalid audience
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsInValidAudience() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/invalid_audience.xml.base64");
settings.setStrict(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
settings.setStrict(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertThat(samlResponse.getError(), containsString("is not a valid audience for this Response"));
}
/**
* Tests the isValid method of SamlResponse
* Case: invalid issuer
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsInValidIssuer() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/invalid_issuer_assertion.xml.base64");
settings.setStrict(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
settings.setStrict(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("Invalid issuer in the Assertion/Response. Was 'http://invalid.issuer.example.com/', but expected 'http://idp.example.com/'", samlResponse.getError());
settings.setStrict(false);
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/invalid_issuer_message.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
settings.setStrict(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
}
/**
* Tests the isValid method of SamlResponse
* Case: invalid SessionIndex
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsInValidSessionIndex() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/invalid_sessionindex.xml.base64");
settings.setStrict(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
settings.setStrict(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("The attributes have expired, based on the SessionNotOnOrAfter of the AttributeStatement of this Response", samlResponse.getError());
}
@Test
public void testIsValidSubjectConfirmation_noSubjectConfirmationMethod() throws Exception {
final Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
final String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_subjectconfirmation_method.xml.base64");
assertResponseValid(settings, samlResponseEncoded, false, false, "No Signature found. SAML Response rejected");
assertResponseValid(settings, samlResponseEncoded, true, false, "A valid SubjectConfirmation was not found on this Response");
}
@Test
public void testIsValidSubjectConfirmation_noSubjectConfirmationData() throws Exception {
final Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
final String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_subjectconfirmation_data.xml.base64");
assertResponseValid(settings, samlResponseEncoded, false, false, "No Signature found. SAML Response rejected");
assertResponseValid(settings, samlResponseEncoded, true, false, "A valid SubjectConfirmation was not found on this Response");
}
@Test
public void testIsValidSubjectConfirmation_invalidInResponseTo() throws Exception {
final Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
final String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/invalid_subjectconfirmation_inresponse.xml.base64");
assertResponseValid(settings, samlResponseEncoded, false, false, "No Signature found. SAML Response rejected");
assertResponseValid(settings, samlResponseEncoded, true, false, "A valid SubjectConfirmation was not found on this Response: SubjectConfirmationData has an invalid InResponseTo value");
}
@Test
public void testIsValidSubjectConfirmation_unmatchedInResponseTo() throws Exception {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
settings.setWantAssertionsSigned(false);
settings.setWantMessagesSigned(true);
final String samlResponseEncoded = loadSignMessageAndEncode("data/responses/invalids/invalid_unpaired_inresponsesto.xml");
assertResponseValid(settings, samlResponseEncoded, true, false,
"A valid SubjectConfirmation was not found on this Response: SubjectConfirmationData has an invalid InResponseTo value");
assertResponseValid(settings, samlResponseEncoded, false, true, null);
}
@Test
public void testIsValidSubjectConfirmation_invalidRecipient() throws Exception {
final Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
final String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/invalid_subjectconfirmation_recipient.xml.base64");
assertResponseValid(settings, samlResponseEncoded, false, false, "No Signature found. SAML Response rejected");
assertResponseValid(settings, samlResponseEncoded, true, false, "A valid SubjectConfirmation was not found on this Response: SubjectConfirmationData doesn't match a valid Recipient");
}
@Test
public void testIsValidSubjectConfirmation_noLongerValid() throws Exception {
final Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
final String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/invalid_subjectconfirmation_noa.xml.base64");
assertResponseValid(settings, samlResponseEncoded, false, false, "No Signature found. SAML Response rejected");
assertResponseValid(settings, samlResponseEncoded, true, false, "A valid SubjectConfirmation was not found on this Response: SubjectConfirmationData is no longer valid");
}
@Test
public void testIsValidSubjectConfirmation_notYetValid() throws Exception {
final Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
final String samlResponseEncoded = loadAndEncode("data/responses/invalids/invalid_subjectconfirmation_nb.xml");
assertResponseValid(settings, samlResponseEncoded, false, false, "No Signature found. SAML Response rejected");
assertResponseValid(settings, samlResponseEncoded, true, false, "A valid SubjectConfirmation was not found on this Response: SubjectConfirmationData is not yet valid");
}
@Test
public void testIsValidSubjectConfirmation_missingRecipient() throws Exception {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
settings.setWantAssertionsSigned(false);
settings.setWantMessagesSigned(true);
final String samlResponseEncoded = loadSignMessageAndEncode("data/responses/invalids/invalid_subjectconfirmation_no_recipient.xml");
assertResponseValid(settings, samlResponseEncoded, false, true, null);
assertResponseValid(settings, samlResponseEncoded, true, false,
"A valid SubjectConfirmation was not found on this Response: SubjectConfirmationData doesn't contain a Recipient");
}
@Test
public void testIsValidSubjectConfirmation_missingNotOnOrAfter() throws Exception {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
settings.setWantAssertionsSigned(false);
settings.setWantMessagesSigned(true);
final String samlResponseEncoded = loadSignMessageAndEncode("data/responses/invalids/invalid_subjectconfirmation_no_notonorafter.xml");
assertResponseValid(settings, samlResponseEncoded, false, true, null);
assertResponseValid(settings, samlResponseEncoded, true, false,
"A valid SubjectConfirmation was not found on this Response: SubjectConfirmationData doesn't contain a NotOnOrAfter attribute");
}
@Test
public void testIsValidSubjectConfirmation_multipleIssues() throws Exception {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
settings.setWantAssertionsSigned(false);
settings.setWantMessagesSigned(true);
final String samlResponseEncoded = loadSignMessageAndEncode("data/responses/invalids/invalid_subjectconfirmation_multiple_issues.xml");
assertResponseValid(settings, samlResponseEncoded, false, true, null);
assertResponseValid(settings, samlResponseEncoded, true, false,
"A valid SubjectConfirmation was not found on this Response: " +
"\n[0] SubjectConfirmationData doesn't contain a NotOnOrAfter attribute, " +
"\n[1] SubjectConfirmationData doesn't contain a Recipient, " +
"\n[2] SubjectConfirmationData is no longer valid");
}
@Test
public void testIsValid_multipleThreads() throws Exception {
// having
final int jobCount = 100;
final int threadCount = 5;
final ExecutorService executor = Executors.newFixedThreadPool(threadCount);
final List<Throwable> errors = new CopyOnWriteArrayList<>();
final AtomicInteger successCount = new AtomicInteger();
// when
for (int i = 0; i < jobCount; i++) {
executor.submit(new Runnable() {
@Override
public void run() {
try {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
settings.setWantAssertionsSigned(false);
settings.setWantMessagesSigned(true);
final String samlResponseEncoded = loadSignMessageAndEncode("data/responses/valid_idp_initiated_response.xml");
assertResponseValid(settings, samlResponseEncoded, true, true, null);
successCount.incrementAndGet();
} catch (Throwable e) {
errors.add(e);
}
}
});
}
executor.shutdown();
executor.awaitTermination(30, TimeUnit.SECONDS);
// then
assertThat(errors, Matchers.empty());
assertThat(successCount.get(), is(jobCount));
}
/**
* Tests the isValid method of SamlResponse
* Case: Datetime with Miliseconds
*
* @throws Error
* @throws IOException
* @throws ValidationError
* @throws SettingsException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
*
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testDatetimeWithMiliseconds() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/unsigned_response_with_miliseconds.xm.base64");
settings.setStrict(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
settings.setStrict(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
}
/**
* Tests the isValid method of SamlResponse
* Case: invalid requestId
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsInValidRequestId() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/valid_response.xml.base64");
settings.setStrict(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.isValid());
assertTrue(samlResponse.isValid("invalidRequestId"));
settings.setStrict(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.isValid());
assertFalse(samlResponse.isValid("invalidRequestId"));
assertThat(samlResponse.getError(), containsString("The InResponseTo of the Response"));
}
@Test
public void testUnexpectedRequestId() throws Exception {
Saml2Settings acceptingUnexpectedInResponseTo = new SettingsBuilder().fromFile("config/config.my.properties").build();
Saml2Settings rejectingUnexpectedInResponseTo = new SettingsBuilder().fromFile("config/config.my.properties").build();
rejectingUnexpectedInResponseTo.setRejectUnsolicitedResponsesWithInResponseTo(true);
final String samlResponseEncoded = Util.getFileAsString("data/responses/valid_response.xml.base64");
assertResponseValid(acceptingUnexpectedInResponseTo, samlResponseEncoded, true, true, null);
assertResponseValid(rejectingUnexpectedInResponseTo, samlResponseEncoded, true, false,
"The Response has an InResponseTo attribute: ONELOGIN_5fe9d6e499b2f0913206aab3f7191729049bb807 while no InResponseTo was expected");
}
@Test
public void testMissingExpectedRequestId() throws Exception {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
settings.setWantMessagesSigned(true);
settings.setWantAssertionsSigned(false);
settings.setStrict(true);
// message with no InResponseTo
final String samlResponseEncoded = loadSignMessageAndEncode("data/responses/valid_idp_initiated_response.xml");
final SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid("expected-id"));
assertEquals(samlResponse.getError(), "The InResponseTo of the Response: null, does not match the ID of the AuthNRequest sent by the SP: expected-id");
}
/**
* Tests the isValid method of SamlResponse
* Case: invalid signing issues
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsInValidSignIssues() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/unsigned_response.xml.base64");
settings.setStrict(false);
settings.setWantAssertionsSigned(false);
settings.setWantMessagesSigned(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
settings.setWantAssertionsSigned(true);
settings.setWantMessagesSigned(false);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
settings.setWantAssertionsSigned(false);
settings.setWantMessagesSigned(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
settings.setWantAssertionsSigned(true);
settings.setWantMessagesSigned(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
settings.setStrict(true);
settings.setWantAssertionsSigned(false);
settings.setWantMessagesSigned(false);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
settings.setWantAssertionsSigned(true);
settings.setWantMessagesSigned(false);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("The Assertion of the Response is not signed and the SP requires it", samlResponse.getError());
settings.setWantAssertionsSigned(false);
settings.setWantMessagesSigned(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("The Message of the Response is not signed and the SP requires it", samlResponse.getError());
settings.setWantAssertionsSigned(true);
settings.setWantMessagesSigned(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("The Assertion of the Response is not signed and the SP requires it", samlResponse.getError());
}
/**
* Tests the isValid method of SamlResponse
* Case: invalid encryption issues
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsInValidEncIssues() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/unsigned_response.xml.base64");
settings.setStrict(false);
settings.setWantAssertionsEncrypted(false);
settings.setWantNameIdEncrypted(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
settings.setWantAssertionsEncrypted(true);
settings.setWantNameIdEncrypted(false);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
settings.setWantAssertionsEncrypted(false);
settings.setWantNameIdEncrypted(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
settings.setWantAssertionsEncrypted(true);
settings.setWantNameIdEncrypted(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
settings.setStrict(true);
settings.setWantAssertionsEncrypted(false);
settings.setWantNameIdEncrypted(false);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
settings.setWantAssertionsEncrypted(true);
settings.setWantNameIdEncrypted(false);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("The assertion of the Response is not encrypted and the SP requires it", samlResponse.getError());
settings.setWantAssertionsEncrypted(false);
settings.setWantNameIdEncrypted(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("The NameID of the Response is not encrypted and the SP requires it", samlResponse.getError());
settings.setWantAssertionsEncrypted(true);
settings.setWantNameIdEncrypted(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("The assertion of the Response is not encrypted and the SP requires it", samlResponse.getError());
}
/**
* Tests the isValid method of SamlResponse
* Case: invalid cert
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsInValidCert() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.invalididpcertstring.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/valid_response.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("Signature validation failed. SAML Response rejected", samlResponse.getError());
}
/**
* Tests the isValid method of SamlResponse
* Case: valid response with different namespaces
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testNamespaceIsValid() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/response_namespaces.xml.base64");
settings.setStrict(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.isValid());
settings.setStrict(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.isValid());
}
/**
* Tests the isValid method of SamlResponse
* Case: valid response from ADFS
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testADFSValid() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.adfs.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/response_adfs1.xml.base64");
settings.setStrict(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.isValid());
settings.setStrict(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.isValid());
}
/**
* Tests the isValid method of SamlResponse
* Case: valid response
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsValid() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/valid_response.xml.base64");
settings.setStrict(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.isValid());
settings.setStrict(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.isValid());
}
/**
* Tests the isValid method of SamlResponse
* Case: valid response validated with certfingerprint
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsValid2() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.mywithnocert.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/valid_response.xml.base64");
settings.setStrict(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.isValid());
settings.setStrict(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.isValid());
}
/**
* Tests the isValid method of SamlResponse
* Case: valid encrypted assertion
*
* @throws Exception
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsValid_doubleSignedEncrypted() throws Exception {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
settings.setWantAssertionsSigned(true);
settings.setWantMessagesSigned(true);
String samlResponseEncoded = Util.getFileAsString("data/responses/double_signed_encrypted_assertion.xml.base64");
assertResponseValid(settings, samlResponseEncoded, false, true, null);
assertResponseValid(settings, samlResponseEncoded, true, true, null);
}
@Test
public void testIsValid_signedResponseEncryptedAssertion() throws Exception {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
settings.setWantAssertionsSigned(false);
settings.setWantMessagesSigned(true);
String samlResponseEncoded = Util.getFileAsString("data/responses/signed_message_encrypted_assertion.xml.base64");
assertResponseValid(settings, samlResponseEncoded, false, true, null);
assertResponseValid(settings, samlResponseEncoded, true, true, null);
settings.setWantAssertionsSigned(true);
assertResponseValid(settings, samlResponseEncoded, false, true, null);
assertResponseValid(settings, samlResponseEncoded, true, false, "The Assertion of the Response is not signed and the SP requires it");
}
@Test
public void testIsValid_signedEncryptedAssertion() throws Exception {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
settings.setWantAssertionsSigned(true);
settings.setWantMessagesSigned(false);
String samlResponseEncoded = Util.getFileAsString("data/responses/signed_encrypted_assertion.xml.base64");
assertResponseValid(settings, samlResponseEncoded, false, true, null);
assertResponseValid(settings, samlResponseEncoded, true, true, null);
settings.setWantMessagesSigned(true);
assertResponseValid(settings, samlResponseEncoded, false, true, null);
assertResponseValid(settings, samlResponseEncoded, true, false, "The Message of the Response is not signed and the SP requires it");
}
/**
* Tests the isValid method of SamlResponse
* Case: valid sign response / sign assertion / both signed
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsValidSign() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
settings.setWantAssertionsSigned(false);
settings.setWantMessagesSigned(false);
String samlResponseEncoded = Util.getFileAsString("data/responses/signed_message_response.xml.base64");
settings.setStrict(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.isValid());
settings.setStrict(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.isValid());
samlResponseEncoded = Util.getFileAsString("data/responses/signed_assertion_response.xml.base64");
settings.setStrict(false);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.isValid());
settings.setStrict(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.isValid());
samlResponseEncoded = Util.getFileAsString("data/responses/double_signed_response.xml.base64");
settings.setStrict(false);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.isValid());
settings.setStrict(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.isValid());
}
/**
* Tests the processSignedElements method of SamlResponse
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#processSignedElements
*/
@Test
public void testProcessSignedElementsInvalidSignElement() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/signed_message_response.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(!samlResponse.processSignedElements().isEmpty());
samlResponseEncoded = Util.getFileAsString("data/responses/signed_assertion_response.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(!samlResponse.processSignedElements().isEmpty());
samlResponseEncoded = Util.getFileAsString("data/responses/double_signed_response.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(!samlResponse.processSignedElements().isEmpty());
samlResponseEncoded = Util.getFileAsString("data/responses/unsigned_response.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertTrue(samlResponse.processSignedElements().isEmpty());
}
/**
* Tests the processSignedElements method of SamlResponse
* Case: invalid Signature Element
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#processSignedElements
*/
@Test
public void testProcessSignedElementsInvalidSignElem() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("Invalid Signature Element {urn:oasis:names:tc:SAML:2.0:assertion}Subject SAML Response rejected");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/wrong_signed_element.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
samlResponse.processSignedElements();
}
/**
* Tests the processSignedElements method of SamlResponse
* Case: another invalid Signature Element
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#processSignedElements
*/
@Test
public void testProcessSignedElementsInvalidSignElem2() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("Invalid Signature Element {urn:oasis:names:tc:SAML:2.0:assertion}Subject SAML Response rejected");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/wrong_signed_element2.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
samlResponse.processSignedElements();
}
/**
* Tests the processSignedElements method of SamlResponse
* Case: invalid id
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#processSignedElements
*/
@Test
public void testProcessSignedElementsNoId() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("Signed Element must contain an ID. SAML Response rejected");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_assertion_id.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
samlResponse.processSignedElements();
}
/**
* Tests the processSignedElements method of SamlResponse
* Case: duplicate reference uri
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#processSignedElements
*/
@Test
public void testProcessSignedElementsDuplicateRef() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
expectedEx.expect(ValidationError.class);
expectedEx.expectMessage("Found an invalid Signed Element. SAML Response rejected");
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
String samlResponseEncoded = Util.getFileAsString("data/responses/invalids/duplicate_reference_uri.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
samlResponse.processSignedElements();
}
/**
* Tests the isValid method of SamlResponse
* Case: invalid signs
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsInValidSign() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
settings.setStrict(true);
String samlResponseEncoded = Util.getFileAsString("data/responses/unsigned_response.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("No Signature found. SAML Response rejected", samlResponse.getError());
settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/triple_signed_response.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("Duplicated ID. SAML Response rejected", samlResponse.getError());
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/signed_assertion_response_with_2signatures.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("Duplicated ID. SAML Response rejected", samlResponse.getError());
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/signed_message_response_with_2signatures.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("Duplicated ID. SAML Response rejected", samlResponse.getError());
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/wrong_signed_element.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("Invalid Signature Element {urn:oasis:names:tc:SAML:2.0:assertion}Subject SAML Response rejected", samlResponse.getError());
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/wrong_signed_element2.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("Invalid Signature Element {urn:oasis:names:tc:SAML:2.0:assertion}Subject SAML Response rejected", samlResponse.getError());
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/duplicate_reference_uri.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("Found an invalid Signed Element. SAML Response rejected", samlResponse.getError());
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/no_assertion_id.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("Signed Element must contain an ID. SAML Response rejected", samlResponse.getError());
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/bad_reference.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertFalse(samlResponse.isValid());
assertEquals("Found an invalid Signed Element. SAML Response rejected", samlResponse.getError());
}
/**
* Tests the validateSignedElements method of SamlResponse
* Case: invalid signs
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#validateSignedElements
*/
@Test
public void testValidateSignedElements() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.min.properties").build();
ArrayList<String> signedElements = new ArrayList<String>();
String samlResponseEncoded = Util.getFileAsString("data/responses/signed_message_response.xml.base64");
Document samlResponseDoc = Util.loadXML(new String(Util.base64decoder(samlResponseEncoded)));
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
NodeList signNodes = Util.query(samlResponseDoc, "//ds:Signature");
assertFalse(samlResponse.validateSignedElements(signedElements));
signedElements = new ArrayList<String>();
for (int i = 0; i < signNodes.getLength(); i++) {
Node signNode = signNodes.item(i);
signedElements.add("{" + signNode.getParentNode().getNamespaceURI() + "}" + signNode.getParentNode().getLocalName());
}
assertTrue(samlResponse.validateSignedElements(signedElements));
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/triple_signed_response.xml.base64");
samlResponseDoc = Util.loadXML(new String(Util.base64decoder(samlResponseEncoded)));
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
signNodes = Util.query(samlResponseDoc, "//ds:Signature");
signedElements = new ArrayList<String>();
for (int i = 0; i < signNodes.getLength(); i++) {
Node signNode = signNodes.item(i);
signedElements.add(signNode.getParentNode().getLocalName());
}
assertFalse(samlResponse.validateSignedElements(signedElements));
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/signed_assertion_response_with_2signatures.xml.base64");
samlResponseDoc = Util.loadXML(new String(Util.base64decoder(samlResponseEncoded)));
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
signNodes = Util.query(samlResponseDoc, "//ds:Signature");
signedElements = new ArrayList<String>();
for (int i = 0; i < signNodes.getLength(); i++) {
Node signNode = signNodes.item(i);
signedElements.add("{" + signNode.getParentNode().getNamespaceURI() + "}" + signNode.getParentNode().getLocalName());
}
assertFalse(samlResponse.validateSignedElements(signedElements));
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/signed_message_response_with_2signatures.xml.base64");
samlResponseDoc = Util.loadXML(new String(Util.base64decoder(samlResponseEncoded)));
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
signNodes = Util.query(samlResponseDoc, "//ds:Signature");
signedElements = new ArrayList<String>();
for (int i = 0; i < signNodes.getLength(); i++) {
Node signNode = signNodes.item(i);
signedElements.add("{" + signNode.getParentNode().getNamespaceURI() + "}" + signNode.getParentNode().getLocalName());
}
assertFalse(samlResponse.validateSignedElements(signedElements));
samlResponseEncoded = Util.getFileAsString("data/responses/invalids/wrong_signed_element.xml.base64");
samlResponseDoc = Util.loadXML(new String(Util.base64decoder(samlResponseEncoded)));
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
signNodes = Util.query(samlResponseDoc, "//ds:Signature");
signedElements = new ArrayList<String>();
for (int i = 0; i < signNodes.getLength(); i++) {
Node signNode = signNodes.item(i);
signedElements.add("{" + signNode.getParentNode().getNamespaceURI() + "}" + signNode.getParentNode().getLocalName());
}
assertFalse(samlResponse.validateSignedElements(signedElements));
}
/**
* Tests the isValid method of SamlResponse
* Case: valid response that has no reference URI
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#isValid
*/
@Test
public void testIsValidSignWithEmptyReferenceURI() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.noreferenceuri.properties").build();
settings.setWantAssertionsSigned(false);
settings.setWantMessagesSigned(false);
final String requestURL = "http://localhost:9001/v1/users/authorize/saml";
String samlResponseEncoded = Util.getFileAsString("data/responses/response_without_reference_uri.xml.base64");
settings.setStrict(false);
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(requestURL, samlResponseEncoded));
assertTrue(samlResponse.isValid());
settings.setStrict(true);
samlResponse = new SamlResponse(settings, newHttpRequest(requestURL, samlResponseEncoded));
assertTrue(samlResponse.isValid());
HashMap<String, List<String>> attributes = samlResponse.getAttributes();
assertFalse(attributes.isEmpty());
String attrName = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";
assertEquals("saml@user.com", attributes.get(attrName).get(0));
}
/**
* Tests the getError method of SamlResponse
*
* @throws ValidationError
* @throws SettingsException
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws Error
*
* @see com.onelogin.saml2.authn.SamlResponse#getError
*/
@Test
public void testGetError() throws IOException, Error, XPathExpressionException, ParserConfigurationException, SAXException, SettingsException, ValidationError {
Saml2Settings settings = new SettingsBuilder().fromFile("config/config.my.properties").build();
settings.setStrict(true);
String samlResponseEncoded = Util.getFileAsString("data/responses/response4.xml.base64");
SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertNull(samlResponse.getError());
samlResponse.isValid();
assertThat(samlResponse.getError(), containsString("SAML Response must contain 1 Assertion."));
settings.setStrict(false);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
samlResponse.isValid();
assertThat(samlResponse.getError(), containsString("SAML Response must contain 1 Assertion."));
samlResponseEncoded = Util.getFileAsString("data/responses/valid_response.xml.base64");
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertNull(samlResponse.getError());
samlResponse.isValid();
assertNull(samlResponse.getError());
settings.setStrict(true);
samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertNull(samlResponse.getError());
samlResponse.isValid();
assertNull(samlResponse.getError());
}
private String loadAndEncode(String path) throws Exception
{
return Util.base64encoder(Util.getFileAsString(path));
}
private String loadSignMessageAndEncode(String path) throws Exception
{
String samlResponse = Util.getFileAsString(path);
final String signed = Util.addSign(Util.convertStringToDocument(samlResponse),
Util.loadPrivateKey(Util.getFileAsString("data/customPath/certs/sp.pem")),
Util.loadCert(Util.getFileAsString("data/customPath/certs/sp.crt")), Constants.RSA_SHA1);
return Util.base64encoder(signed);
}
private void assertResponseValid(Saml2Settings settings, String samlResponseEncoded, boolean strict, boolean expectedValid, String expectedError) throws Exception
{
settings.setStrict(strict);
final SamlResponse samlResponse = new SamlResponse(settings, newHttpRequest(samlResponseEncoded));
assertEquals(expectedValid, samlResponse.isValid());
assertEquals(expectedError, samlResponse.getError());
}
private static HttpRequest newHttpRequest(String samlResponseEncoded) {
return newHttpRequest(ACS_URL, samlResponseEncoded);
}
private static HttpRequest newHttpRequest(String requestURL, String samlResponseEncoded) {
return new HttpRequest(requestURL).addParameter("SAMLResponse", samlResponseEncoded);
}
}