diff --git a/CHANGELOG b/CHANGELOG
index 019196bd..e670d79d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,21 @@
CHANGELOG
=========
+v3.6.0
+* Add AES128_GCM encryption on generateNameId method. New setting parameter encryption_algorithm. If you set a encryption method different than AES128_CBC then the algorithm RSA_OAEP_MGF1P will be used as well instead RSA_1_5
+* PHP 8.0 support
+
+v3.5.1
+* 3.5.0 packagist/github release due a confusion were using the master (2.X branch). I'm releasing 3.5.1 to fix this issue and go back to 3.X branch
+
+v3.5.0
+* [#412](https://github.com/onelogin/php-saml/pull/412) Empty instead of unset the $_SESSION variable
+* [#433](https://github.com/onelogin/php-saml/issues/443) Fix Incorrect Destination in LogoutResponse when using responseUrl #443
+* Update xmlseclibs to 3.1.1
+* Add support for SMARTCARD_PKI and RSA_TOKEN Auth Contexts
+* Get lib path dinamically
+* Check for x509Cert of the IdP when loading settings, even if the security index was not provided
+* Support Statements with Attribute elements with the same name enabling the allowRepeatAttributeName setting
+
v3.4.1
* Add setSchemasPath to Auth class and fix backward compatibility
diff --git a/README.md b/README.md
index 7ad8b48e..d552ecb9 100644
--- a/README.md
+++ b/README.md
@@ -472,7 +472,7 @@ $advancedSettings = array(
// Set to false and no AuthContext will be sent in the AuthNRequest.
// Set true or don't present this parameter and you will get an AuthContext 'exact' 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'.
// Set an array with the possible auth context values: array('urn:oasis:names:tc:SAML:2.0:ac:classes:Password', 'urn:oasis:names:tc:SAML:2.0:ac:classes:X509').
- 'requestedAuthnContext' => true,
+ 'requestedAuthnContext' => false,
// Indicates if the SP will validate all received xmls.
// (In order to validate the xml, 'strict' and 'wantXMLValidation' must be true).
@@ -488,6 +488,10 @@ $advancedSettings = array(
// will be accepted.
'destinationStrictlyMatches' => false,
+ // If true, the toolkit will not raised an error when the Statement Element
+ // contain atribute elements with name duplicated
+ 'allowRepeatAttributeName' => false,
+
// If true, SAMLResponses with an InResponseTo value will be rejectd if not
// AuthNRequest ID provided to the validation method.
'rejectUnsolicitedResponsesWithInResponseTo' => false,
@@ -509,6 +513,17 @@ $advancedSettings = array(
// Notice that sha1 is a deprecated algorithm and should not be used
'digestAlgorithm' => 'http://www.w3.org/2001/04/xmlenc#sha256',
+ // Algorithm that the toolkit will use for encryption process. Options:
+ // 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc'
+ // 'http://www.w3.org/2001/04/xmlenc#aes128-cbc'
+ // 'http://www.w3.org/2001/04/xmlenc#aes192-cbc'
+ // 'http://www.w3.org/2001/04/xmlenc#aes256-cbc'
+ // 'http://www.w3.org/2009/xmlenc11#aes128-gcm'
+ // 'http://www.w3.org/2009/xmlenc11#aes192-gcm'
+ // 'http://www.w3.org/2009/xmlenc11#aes256-gcm';
+ // Notice that aes-cbc are not consider secure anymore so should not be used
+ 'encryption_algorithm' => 'http://www.w3.org/2009/xmlenc11#aes128-gcm',
+
// ADFS URL-Encodes SAML data as lowercase, and the toolkit by default uses
// uppercase. Turn it True for ADFS compatibility on signature verification
'lowercaseUrlencoding' => false,
@@ -1202,7 +1217,7 @@ Main class of OneLogin PHP Toolkit
* `getNameId` - Returns the nameID
* `getNameIdFormat` - Gets the NameID Format provided by the SAML response from the IdP.
* `getNameIdNameQualifier` - Gets the NameID NameQualifier provided from the SAML Response String.
- * `getNameIdNameSPQualifier` - Gets the NameID SP NameQualifier provided from the SAML Response String.
+ * `getNameIdSPNameQualifier` - Gets the NameID SP NameQualifier provided from the SAML Response String.
* `getSessionIndex` - Gets the SessionIndex from the AuthnStatement.
* `getErrors` - Returns if there were any error
* `getSSOurl` - Gets the SSO url.
@@ -1240,7 +1255,7 @@ SAML 2 Authentication Response class
* `getNameId` - Gets the NameID provided by the SAML response from the IdP.
* `getNameIdFormat` - Gets the NameID Format provided by the SAML response from the IdP.
* `getNameIdNameQualifier` - Gets the NameID NameQualifier provided from the SAML Response String.
- * `getNameIdNameSPQualifier` - Gets the NameID SP NameQualifier provided from the SAML Response String.
+ * `getNameIdSPNameQualifier` - Gets the NameID SP NameQualifier provided from the SAML Response String.
* `getSessionNotOnOrAfter` - Gets the SessionNotOnOrAfter from the
AuthnStatement
* `getSessionIndex` - Gets the SessionIndex from the AuthnStatement.
diff --git a/advanced_settings_example.php b/advanced_settings_example.php
index 1d1552ce..d9c16e28 100644
--- a/advanced_settings_example.php
+++ b/advanced_settings_example.php
@@ -91,6 +91,10 @@
// will be accepted.
'destinationStrictlyMatches' => false,
+ // If true, the toolkit will not raised an error when the Statement Element
+ // contain atribute elements with name duplicated
+ 'allowRepeatAttributeName' => false,
+
// If true, SAMLResponses with an InResponseTo value will be rejectd if not
// AuthNRequest ID provided to the validation method.
'rejectUnsolicitedResponsesWithInResponseTo' => false,
@@ -112,6 +116,17 @@
// Notice that sha1 is a deprecated algorithm and should not be used
'digestAlgorithm' => 'http://www.w3.org/2001/04/xmlenc#sha256',
+ // Algorithm that the toolkit will use for encryption process. Options:
+ // 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc'
+ // 'http://www.w3.org/2001/04/xmlenc#aes128-cbc'
+ // 'http://www.w3.org/2001/04/xmlenc#aes192-cbc'
+ // 'http://www.w3.org/2001/04/xmlenc#aes256-cbc'
+ // 'http://www.w3.org/2009/xmlenc11#aes128-gcm'
+ // 'http://www.w3.org/2009/xmlenc11#aes192-gcm'
+ // 'http://www.w3.org/2009/xmlenc11#aes256-gcm';
+ // Notice that aes-cbc are not consider secure anymore so should not be used
+ 'encryption_algorithm' => 'http://www.w3.org/2009/xmlenc11#aes128-gcm',
+
// ADFS URL-Encodes SAML data as lowercase, and the toolkit by default uses
// uppercase. Turn it True for ADFS compatibility on signature verification
'lowercaseUrlencoding' => false,
diff --git a/composer.json b/composer.json
index 2cae8af8..3aa198da 100644
--- a/composer.json
+++ b/composer.json
@@ -16,11 +16,11 @@
},
"require": {
"php": ">=5.4",
- "robrichards/xmlseclibs": ">=3.0.4"
+ "robrichards/xmlseclibs": ">=3.1.1"
},
"require-dev": {
+ "phpunit/phpunit": "<7.5.18",
"php-coveralls/php-coveralls": "^1.0.2 || ^2.0",
- "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1",
"sebastian/phpcpd": "^2.0 || ^3.0 || ^4.0",
"phploc/phploc": "^2.1 || ^3.0 || ^4.0",
"pdepend/pdepend": "^2.5.0",
diff --git a/demo1/index.php b/demo1/index.php
index c7dd7f86..122ac500 100644
--- a/demo1/index.php
+++ b/demo1/index.php
@@ -77,6 +77,9 @@
if (!empty($errors)) {
echo '
' . implode(', ', $errors) . '
';
+ if ($auth->getSettings()->isDebugActive()) {
+ echo ''.$auth->getLastErrorReason().'
';
+ }
}
if (!$auth->isAuthenticated()) {
@@ -108,6 +111,9 @@
echo 'Sucessfully logged out
';
} else {
echo '' . implode(', ', $errors) . '
';
+ if ($auth->getSettings()->isDebugActive()) {
+ echo ''.$auth->getLastErrorReason().'
';
+ }
}
}
diff --git a/src/Saml2/Auth.php b/src/Saml2/Auth.php
index 5f603a17..70a87152 100644
--- a/src/Saml2/Auth.php
+++ b/src/Saml2/Auth.php
@@ -618,46 +618,37 @@ public function logout($returnTo = null, array $parameters = array(), $nameId =
return $this->redirectTo($sloUrl, $parameters, $stay);
}
- /**
- * Gets the SSO url.
+ /**
+ * Gets the IdP SSO url.
*
- * @return string The url of the Single Sign On Service
+ * @return string The url of the IdP Single Sign On Service
*/
public function getSSOurl()
{
- $idpData = $this->_settings->getIdPData();
- return $idpData['singleSignOnService']['url'];
+ return $this->_settings->getIdPSSOUrl();
}
/**
- * Gets the SLO url.
+ * Gets the IdP SLO url.
*
- * @return string|null The url of the Single Logout Service
+ * @return string|null The url of the IdP Single Logout Service
*/
public function getSLOurl()
{
- $url = null;
- $idpData = $this->_settings->getIdPData();
- if (isset($idpData['singleLogoutService']) && isset($idpData['singleLogoutService']['url'])) {
- $url = $idpData['singleLogoutService']['url'];
- }
- return $url;
+ return $this->_settings->getIdPSLOUrl();
}
/**
- * Gets the SLO response url.
+ * Gets the IdP SLO response url.
*
- * @return string|null The response url of the Single Logout Service
+ * @return string|null The response url of the IdP Single Logout Service
*/
public function getSLOResponseUrl()
{
- $idpData = $this->_settings->getIdPData();
- if (isset($idpData['singleLogoutService']) && isset($idpData['singleLogoutService']['responseUrl'])) {
- return $idpData['singleLogoutService']['responseUrl'];
- }
- return $this->getSLOurl();
+ return $this->_settings->getIdPSLOResponseUrl();
}
+
/**
* Gets the ID of the last AuthNRequest or LogoutRequest generated by the Service Provider.
*
diff --git a/src/Saml2/AuthnRequest.php b/src/Saml2/AuthnRequest.php
index a1311f71..fd9afb53 100644
--- a/src/Saml2/AuthnRequest.php
+++ b/src/Saml2/AuthnRequest.php
@@ -55,7 +55,6 @@ public function __construct(\OneLogin\Saml2\Settings $settings, $forceAuthn = fa
$this->_settings = $settings;
$spData = $this->_settings->getSPData();
- $idpData = $this->_settings->getIdPData();
$security = $this->_settings->getSecurityData();
$id = Utils::generateUniqueID();
@@ -150,6 +149,7 @@ public function __construct(\OneLogin\Saml2\Settings $settings, $forceAuthn = fa
$spEntityId = htmlspecialchars($spData['entityId'], ENT_QUOTES);
$acsUrl = htmlspecialchars($spData['assertionConsumerService']['url'], ENT_QUOTES);
+ $destination = $this->_settings->getIdPSSOUrl();
$request = <<
{$spEntityId}{$subjectStr}{$nameIdPolicyStr}{$requestedAuthnStr}
diff --git a/src/Saml2/Constants.php b/src/Saml2/Constants.php
index 21261fb2..1b467dd6 100644
--- a/src/Saml2/Constants.php
+++ b/src/Saml2/Constants.php
@@ -64,9 +64,11 @@ class Constants
const AC_PASSWORD_PROTECTED = 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport';
const AC_X509 = 'urn:oasis:names:tc:SAML:2.0:ac:classes:X509';
const AC_SMARTCARD = 'urn:oasis:names:tc:SAML:2.0:ac:classes:Smartcard';
+ const AC_SMARTCARD_PKI = 'urn:oasis:names:tc:SAML:2.0:ac:classes:SmartcardPKI';
const AC_KERBEROS = 'urn:oasis:names:tc:SAML:2.0:ac:classes:Kerberos';
const AC_WINDOWS = 'urn:federation:authentication:windows';
const AC_TLS = 'urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient';
+ const AC_RSATOKEN = 'urn:oasis:names:tc:SAML:2.0:ac:classes:TimeSyncToken';
// Subject Confirmation
const CM_BEARER = 'urn:oasis:names:tc:SAML:2.0:cm:bearer';
diff --git a/src/Saml2/LogoutRequest.php b/src/Saml2/LogoutRequest.php
index d540c22e..108c49be 100644
--- a/src/Saml2/LogoutRequest.php
+++ b/src/Saml2/LogoutRequest.php
@@ -122,12 +122,14 @@ public function __construct(\OneLogin\Saml2\Settings $settings, $request = null,
$nameIdSPNameQualifier,
$nameIdFormat,
$cert,
- $nameIdNameQualifier
+ $nameIdNameQualifier,
+ $security['encryption_algorithm']
);
$sessionIndexStr = isset($sessionIndex) ? "{$sessionIndex}" : "";
$spEntityId = htmlspecialchars($spData['entityId'], ENT_QUOTES);
+ $destination = $this->_settings->getIdPSLOUrl();
$logoutRequest = <<
+ Destination="{$destination}">
{$spEntityId}
{$nameIdObj}
{$sessionIndexStr}
diff --git a/src/Saml2/LogoutResponse.php b/src/Saml2/LogoutResponse.php
index 700feb02..9c3f020e 100644
--- a/src/Saml2/LogoutResponse.php
+++ b/src/Saml2/LogoutResponse.php
@@ -258,19 +258,18 @@ public function build($inResponseTo)
{
$spData = $this->_settings->getSPData();
- $idpData = $this->_settings->getIdPData();
$this->id = Utils::generateUniqueID();
$issueInstant = Utils::parseTime2SAML(time());
-
$spEntityId = htmlspecialchars($spData['entityId'], ENT_QUOTES);
+ $destination = $this->_settings->getIdPSLOResponseUrl();
$logoutResponse = <<
{$spEntityId}
diff --git a/src/Saml2/Response.php b/src/Saml2/Response.php
index b34297f4..a2f8d6dd 100644
--- a/src/Saml2/Response.php
+++ b/src/Saml2/Response.php
@@ -804,6 +804,9 @@ private function _getAttributesByKeyName($keyName = "Name")
{
$attributes = array();
$entries = $this->_queryAssertion('/saml:AttributeStatement/saml:Attribute');
+
+ $security = $this->_settings->getSecurityData();
+ $allowRepeatAttributeName = $security['allowRepeatAttributeName'];
/** @var $entry DOMNode */
foreach ($entries as $entry) {
$attributeKeyNode = $entry->attributes->getNamedItem($keyName);
@@ -812,10 +815,12 @@ private function _getAttributesByKeyName($keyName = "Name")
}
$attributeKeyName = $attributeKeyNode->nodeValue;
if (in_array($attributeKeyName, array_keys($attributes))) {
- throw new ValidationError(
- "Found an Attribute element with duplicated ".$keyName,
- ValidationError::DUPLICATED_ATTRIBUTE_NAME_FOUND
- );
+ if (!$allowRepeatAttributeName) {
+ throw new ValidationError(
+ "Found an Attribute element with duplicated ".$keyName,
+ ValidationError::DUPLICATED_ATTRIBUTE_NAME_FOUND
+ );
+ }
}
$attributeValues = array();
foreach ($entry->childNodes as $childNode) {
@@ -824,7 +829,12 @@ private function _getAttributesByKeyName($keyName = "Name")
$attributeValues[] = $childNode->nodeValue;
}
}
- $attributes[$attributeKeyName] = $attributeValues;
+
+ if (in_array($attributeKeyName, array_keys($attributes))) {
+ $attributes[$attributeKeyName] = array_merge($attributes[$attributeKeyName], $attributeValues);
+ } else {
+ $attributes[$attributeKeyName] = $attributeValues;
+ }
}
return $attributes;
}
diff --git a/src/Saml2/Settings.php b/src/Saml2/Settings.php
index 3c953fc9..43457bad 100644
--- a/src/Saml2/Settings.php
+++ b/src/Saml2/Settings.php
@@ -164,7 +164,7 @@ private function _loadPaths()
'base' => $basePath,
'config' => $basePath,
'cert' => $basePath.'certs/',
- 'lib' => $basePath.'src/Saml2/'
+ 'lib' => __DIR__ . '/',
);
if (defined('ONELOGIN_CUSTOMPATH')) {
@@ -397,6 +397,11 @@ private function _addDefaultValues()
$this->_security['destinationStrictlyMatches'] = false;
}
+ // Allow duplicated Attribute Names
+ if (!isset($this->_security['allowRepeatAttributeName'])) {
+ $this->_security['allowRepeatAttributeName'] = false;
+ }
+
// InResponseTo
if (!isset($this->_security['rejectUnsolicitedResponsesWithInResponseTo'])) {
$this->_security['rejectUnsolicitedResponsesWithInResponseTo'] = false;
@@ -425,6 +430,11 @@ private function _addDefaultValues()
$this->_security['digestAlgorithm'] = XMLSecurityDSig::SHA256;
}
+ // EncryptionAlgorithm
+ if (!isset($this->_security['encryption_algorithm'])) {
+ $this->_security['encryption_algorithm'] = XMLSecurityKey::AES128_CBC;
+ }
+
if (!isset($this->_security['lowercaseUrlencoding'])) {
$this->_security['lowercaseUrlencoding'] = false;
}
@@ -552,19 +562,18 @@ public function checkIdPSettings(array $settings)
$errors[] = 'idp_slo_response_url_invalid';
}
- if (isset($settings['security'])) {
- $security = $settings['security'];
+ $existsX509 = isset($idp['x509cert']) && !empty($idp['x509cert']);
+ $existsMultiX509Sign = isset($idp['x509certMulti']) && isset($idp['x509certMulti']['signing']) && !empty($idp['x509certMulti']['signing']);
+ $existsFingerprint = isset($idp['certFingerprint']) && !empty($idp['certFingerprint']);
+ if (!($existsX509 || $existsFingerprint || $existsMultiX509Sign)
+ ) {
+ $errors[] = 'idp_cert_or_fingerprint_not_found_and_required';
+ }
- $existsX509 = isset($idp['x509cert']) && !empty($idp['x509cert']);
- $existsMultiX509Sign = isset($idp['x509certMulti']) && isset($idp['x509certMulti']['signing']) && !empty($idp['x509certMulti']['signing']);
+ if (isset($settings['security'])) {
$existsMultiX509Enc = isset($idp['x509certMulti']) && isset($idp['x509certMulti']['encryption']) && !empty($idp['x509certMulti']['encryption']);
- $existsFingerprint = isset($idp['certFingerprint']) && !empty($idp['certFingerprint']);
- if (!($existsX509 || $existsFingerprint || $existsMultiX509Sign)
- ) {
- $errors[] = 'idp_cert_or_fingerprint_not_found_and_required';
- }
- if ((isset($security['nameIdEncrypted']) && $security['nameIdEncrypted'] == true)
+ if ((isset($settings['security']['nameIdEncrypted']) && $settings['security']['nameIdEncrypted'] == true)
&& !($existsX509 || $existsMultiX509Enc)
) {
$errors[] = 'idp_cert_not_found_and_required';
@@ -821,6 +830,47 @@ public function shouldCompressResponses()
return $this->_compress['responses'];
}
+ /**
+ * Gets the IdP SSO url.
+ *
+ * @return string|null The url of the IdP Single Sign On Service
+ */
+ public function getIdPSSOUrl()
+ {
+ $ssoUrl = null;
+ if (isset($this->_idp['singleSignOnService']) && isset($this->_idp['singleSignOnService']['url'])) {
+ $ssoUrl = $this->_idp['singleSignOnService']['url'];
+ }
+ return $ssoUrl;
+ }
+
+ /**
+ * Gets the IdP SLO url.
+ *
+ * @return string|null The request url of the IdP Single Logout Service
+ */
+ public function getIdPSLOUrl()
+ {
+ $sloUrl = null;
+ if (isset($this->_idp['singleLogoutService']) && isset($this->_idp['singleLogoutService']['url'])) {
+ $sloUrl = $this->_idp['singleLogoutService']['url'];
+ }
+ return $sloUrl;
+ }
+
+ /**
+ * Gets the IdP SLO response url.
+ *
+ * @return string|null The response url of the IdP Single Logout Service
+ */
+ public function getIdPSLOResponseUrl()
+ {
+ if (isset($this->_idp['singleLogoutService']) && isset($this->_idp['singleLogoutService']['responseUrl'])) {
+ return $this->_idp['singleLogoutService']['responseUrl'];
+ }
+ return $this->getIdPSLOUrl();
+ }
+
/**
* Gets the SP metadata. The XML representation.
*
diff --git a/src/Saml2/Utils.php b/src/Saml2/Utils.php
index 50d3d41b..47debedc 100644
--- a/src/Saml2/Utils.php
+++ b/src/Saml2/Utils.php
@@ -82,11 +82,16 @@ public static function loadXML(DOMDocument $dom, $xml)
assert($dom instanceof DOMDocument);
assert(is_string($xml));
- $oldEntityLoader = libxml_disable_entity_loader(true);
+ $oldEntityLoader = null;
+ if (PHP_VERSION_ID < 80000) {
+ $oldEntityLoader = libxml_disable_entity_loader(true);
+ }
$res = $dom->loadXML($xml);
- libxml_disable_entity_loader($oldEntityLoader);
+ if (PHP_VERSION_ID < 80000) {
+ libxml_disable_entity_loader($oldEntityLoader);
+ }
foreach ($dom->childNodes as $child) {
if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
@@ -141,9 +146,14 @@ public static function validateXML($xml, $schema, $debug = false, $schemaPath =
$schemaFile = __DIR__ . '/schemas/' . $schema;
}
- $oldEntityLoader = libxml_disable_entity_loader(false);
+ $oldEntityLoader = null;
+ if (PHP_VERSION_ID < 80000) {
+ $oldEntityLoader = libxml_disable_entity_loader(false);
+ }
$res = $dom->schemaValidate($schemaFile);
- libxml_disable_entity_loader($oldEntityLoader);
+ if (PHP_VERSION_ID < 80000) {
+ libxml_disable_entity_loader($oldEntityLoader);
+ }
if (!$res) {
$xmlErrors = libxml_get_errors();
syslog(LOG_INFO, 'Error validating the metadata: '.var_export($xmlErrors, true));
@@ -964,12 +974,12 @@ public static function isSessionStarted()
*/
public static function deleteLocalSession()
{
-
if (Utils::isSessionStarted()) {
+ session_unset();
session_destroy();
+ } else {
+ $_SESSION = array();
}
-
- unset($_SESSION);
}
/**
@@ -1046,12 +1056,13 @@ public static function formatFingerPrint($fingerprint)
* @param string|null $format SP Format
* @param string|null $cert IdP Public cert to encrypt the nameID
* @param string|null $nq IdP Name Qualifier
+ * @param string|null $encAlg Encryption algorithm
*
* @return string $nameIDElement DOMElement | XMLSec nameID
*
* @throws Exception
*/
- public static function generateNameId($value, $spnq, $format = null, $cert = null, $nq = null)
+ public static function generateNameId($value, $spnq, $format = null, $cert = null, $nq = null, $encAlg = XMLSecurityKey::AES128_CBC)
{
$doc = new DOMDocument();
@@ -1071,14 +1082,18 @@ public static function generateNameId($value, $spnq, $format = null, $cert = nul
$doc->appendChild($nameId);
if (!empty($cert)) {
- $seckey = new XMLSecurityKey(XMLSecurityKey::RSA_1_5, array('type'=>'public'));
+ if ($encAlg == XMLSecurityKey::AES128_CBC) {
+ $seckey = new XMLSecurityKey(XMLSecurityKey::RSA_1_5, array('type'=>'public'));
+ } else {
+ $seckey = new XMLSecurityKey(XMLSecurityKey::RSA_OAEP_MGF1P, array('type'=>'public'));
+ }
$seckey->loadKey($cert);
$enc = new XMLSecEnc();
$enc->setNode($nameId);
$enc->type = XMLSecEnc::Element;
- $symmetricKey = new XMLSecurityKey(XMLSecurityKey::AES128_CBC);
+ $symmetricKey = new XMLSecurityKey($encAlg);
$symmetricKey->generateSessionKey();
$enc->encryptKey($seckey, $symmetricKey);
@@ -1390,7 +1405,7 @@ public static function addSign($xml, $key, $cert, $signAlgorithm = XMLSecurityKe
* Validates a signature (Message or Assertion).
*
* @param string|\DomNode $xml The element we should validate
- * @param string|null $cert The pubic cert
+ * @param string|null $cert The public cert
* @param string|null $fingerprint The fingerprint of the public cert
* @param string|null $fingerprintalg The algorithm used to get the fingerprint
* @param string|null $xpath The xpath of the signed element
diff --git a/src/Saml2/version.json b/src/Saml2/version.json
index 0fdfc333..5db8ae85 100644
--- a/src/Saml2/version.json
+++ b/src/Saml2/version.json
@@ -1,7 +1,7 @@
{
"php-saml": {
- "version": "3.4.1",
- "released": "25/11/2019"
+ "version": "3.6.0",
+ "released": "19/02/2021"
}
}
diff --git a/tests/data/responses/invalids/invalid_subjectconfirmation_nb.xml.base64 b/tests/data/responses/invalids/invalid_subjectconfirmation_nb.xml.base64
index ff6d371c..de582bfb 100644
--- a/tests/data/responses/invalids/invalid_subjectconfirmation_nb.xml.base64
+++ b/tests/data/responses/invalids/invalid_subjectconfirmation_nb.xml.base64
@@ -1 +1 @@
-PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c2FtbHA6UmVzcG9uc2UgeG1sbnM6c2FtbHA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgeG1sbnM6c2FtbD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9InBmeGMzMmFlZDY3LTgyMGYtNDI5Ni0wYzIwLTIwNWExMGRkNTc4NyIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDYtMTdUMTQ6NTQ6MTRaIiBEZXN0aW5hdGlvbj0iaHR0cDovL3N0dWZmLmNvbS9lbmRwb2ludHMvZW5kcG9pbnRzL2Fjcy5waHAiIEluUmVzcG9uc2VUbz0iXzU3YmNiZjcwLTdiMWYtMDEyZS1jODIxLTc4MmJjYjEzYmIzOCI+DQogIDxzYW1sOklzc3Vlcj5odHRwOi8vaWRwLmV4YW1wbGUuY29tLzwvc2FtbDpJc3N1ZXI+DQogIDxzYW1scDpTdGF0dXM+DQogICAgPHNhbWxwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPg0KICA8L3NhbWxwOlN0YXR1cz4NCiAgPHNhbWw6QXNzZXJ0aW9uIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhtbG5zOnhzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIgSUQ9InBmeDc4NDE5OTFjLWM3M2YtNDAzNS1lMmVlLWMxNzBjMGUxZDNlNCIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDYtMTdUMTQ6NTQ6MTRaIj4NCiAgICA8c2FtbDpJc3N1ZXI+aHR0cDovL2lkcC5leGFtcGxlLmNvbS88L3NhbWw6SXNzdWVyPiAgICANCiAgICA8c2FtbDpTdWJqZWN0Pg0KICAgICAgPHNhbWw6TmFtZUlEIFNQTmFtZVF1YWxpZmllcj0iaGVsbG8uY29tIiBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjEuMTpuYW1laWQtZm9ybWF0OmVtYWlsQWRkcmVzcyI+c29tZW9uZUBleGFtcGxlLmNvbTwvc2FtbDpOYW1lSUQ+DQogICAgICA8c2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uIE1ldGhvZD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmNtOmJlYXJlciI+DQogICAgICAgIDxzYW1sOlN1YmplY3RDb25maXJtYXRpb25EYXRhIE5vdEJlZm9yZT0iMjAyMC0wNi0xN1QxNDo1OToxNFoiIFJlY2lwaWVudD0iaHR0cDovL3N0dWZmLmNvbS9lbmRwb2ludHMvZW5kcG9pbnRzL2Fjcy5waHAiIEluUmVzcG9uc2VUbz0iXzU3YmNiZjcwLTdiMWYtMDEyZS1jODIxLTc4MmJjYjEzYmIzOCIvPg0KICAgICAgPC9zYW1sOlN1YmplY3RDb25maXJtYXRpb24+DQogICAgPC9zYW1sOlN1YmplY3Q+DQogICAgPHNhbWw6Q29uZGl0aW9ucyBOb3RCZWZvcmU9IjIwMTAtMDYtMTdUMTQ6NTM6NDRaIiBOb3RPbk9yQWZ0ZXI9IjIwMjEtMDYtMTdUMTQ6NTk6MTRaIj4NCiAgICAgIDxzYW1sOkF1ZGllbmNlUmVzdHJpY3Rpb24+DQogICAgICAgIDxzYW1sOkF1ZGllbmNlPmh0dHA6Ly9zdHVmZi5jb20vZW5kcG9pbnRzL21ldGFkYXRhLnBocDwvc2FtbDpBdWRpZW5jZT4NCiAgICAgIDwvc2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPg0KICAgIDwvc2FtbDpDb25kaXRpb25zPg0KICAgIDxzYW1sOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAxMS0wNi0xN1QxNDo1NDowN1oiIFNlc3Npb25Ob3RPbk9yQWZ0ZXI9IjIwMjEtMDYtMTdUMjI6NTQ6MTRaIiBTZXNzaW9uSW5kZXg9Il81MWJlMzc5NjVmZWI1NTc5ZDgwMzE0MTA3NjkzNmRjMmU5ZDFkOThlYmYiPg0KICAgICAgPHNhbWw6QXV0aG5Db250ZXh0Pg0KICAgICAgICA8c2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZDwvc2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj4NCiAgICAgIDwvc2FtbDpBdXRobkNvbnRleHQ+DQogICAgPC9zYW1sOkF1dGhuU3RhdGVtZW50Pg0KICAgIDxzYW1sOkF0dHJpYnV0ZVN0YXRlbWVudD4NCiAgICAgIDxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJtYWlsIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OmJhc2ljIj4NCiAgICAgICAgPHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+c29tZW9uZUBleGFtcGxlLmNvbTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT4NCiAgICAgIDwvc2FtbDpBdHRyaWJ1dGU+DQogICAgPC9zYW1sOkF0dHJpYnV0ZVN0YXRlbWVudD4NCiAgPC9zYW1sOkFzc2VydGlvbj4NCjwvc2FtbHA6UmVzcG9uc2U+
+PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c2FtbHA6UmVzcG9uc2UgeG1sbnM6c2FtbHA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgeG1sbnM6c2FtbD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9InBmeGMzMmFlZDY3LTgyMGYtNDI5Ni0wYzIwLTIwNWExMGRkNTc4NyIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDYtMTdUMTQ6NTQ6MTRaIiBEZXN0aW5hdGlvbj0iaHR0cDovL3N0dWZmLmNvbS9lbmRwb2ludHMvZW5kcG9pbnRzL2Fjcy5waHAiIEluUmVzcG9uc2VUbz0iXzU3YmNiZjcwLTdiMWYtMDEyZS1jODIxLTc4MmJjYjEzYmIzOCI+DQogIDxzYW1sOklzc3Vlcj5odHRwOi8vaWRwLmV4YW1wbGUuY29tLzwvc2FtbDpJc3N1ZXI+DQogIDxzYW1scDpTdGF0dXM+DQogICAgPHNhbWxwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPg0KICA8L3NhbWxwOlN0YXR1cz4NCiAgPHNhbWw6QXNzZXJ0aW9uIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhtbG5zOnhzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIgSUQ9InBmeDc4NDE5OTFjLWM3M2YtNDAzNS1lMmVlLWMxNzBjMGUxZDNlNCIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDYtMTdUMTQ6NTQ6MTRaIj4NCiAgICA8c2FtbDpJc3N1ZXI+aHR0cDovL2lkcC5leGFtcGxlLmNvbS88L3NhbWw6SXNzdWVyPiAgICANCiAgICA8c2FtbDpTdWJqZWN0Pg0KICAgICAgPHNhbWw6TmFtZUlEIFNQTmFtZVF1YWxpZmllcj0iaGVsbG8uY29tIiBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjEuMTpuYW1laWQtZm9ybWF0OmVtYWlsQWRkcmVzcyI+c29tZW9uZUBleGFtcGxlLmNvbTwvc2FtbDpOYW1lSUQ+DQogICAgICA8c2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uIE1ldGhvZD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmNtOmJlYXJlciI+DQogICAgICAgIDxzYW1sOlN1YmplY3RDb25maXJtYXRpb25EYXRhIE5vdEJlZm9yZT0iMjk5OS0wNi0xN1QxNDo1OToxNFoiIFJlY2lwaWVudD0iaHR0cDovL3N0dWZmLmNvbS9lbmRwb2ludHMvZW5kcG9pbnRzL2Fjcy5waHAiIEluUmVzcG9uc2VUbz0iXzU3YmNiZjcwLTdiMWYtMDEyZS1jODIxLTc4MmJjYjEzYmIzOCIvPg0KICAgICAgPC9zYW1sOlN1YmplY3RDb25maXJtYXRpb24+DQogICAgPC9zYW1sOlN1YmplY3Q+DQogICAgPHNhbWw6Q29uZGl0aW9ucyBOb3RCZWZvcmU9IjIwMTAtMDYtMTdUMTQ6NTM6NDRaIiBOb3RPbk9yQWZ0ZXI9IjI5OTktMDYtMTdUMTQ6NTk6MTRaIj4NCiAgICAgIDxzYW1sOkF1ZGllbmNlUmVzdHJpY3Rpb24+DQogICAgICAgIDxzYW1sOkF1ZGllbmNlPmh0dHA6Ly9zdHVmZi5jb20vZW5kcG9pbnRzL21ldGFkYXRhLnBocDwvc2FtbDpBdWRpZW5jZT4NCiAgICAgIDwvc2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPg0KICAgIDwvc2FtbDpDb25kaXRpb25zPg0KICAgIDxzYW1sOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAxMS0wNi0xN1QxNDo1NDowN1oiIFNlc3Npb25Ob3RPbk9yQWZ0ZXI9IjI5OTktMDYtMTdUMjI6NTQ6MTRaIiBTZXNzaW9uSW5kZXg9Il81MWJlMzc5NjVmZWI1NTc5ZDgwMzE0MTA3NjkzNmRjMmU5ZDFkOThlYmYiPg0KICAgICAgPHNhbWw6QXV0aG5Db250ZXh0Pg0KICAgICAgICA8c2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZDwvc2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj4NCiAgICAgIDwvc2FtbDpBdXRobkNvbnRleHQ+DQogICAgPC9zYW1sOkF1dGhuU3RhdGVtZW50Pg0KICAgIDxzYW1sOkF0dHJpYnV0ZVN0YXRlbWVudD4NCiAgICAgIDxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJtYWlsIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OmJhc2ljIj4NCiAgICAgICAgPHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+c29tZW9uZUBleGFtcGxlLmNvbTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT4NCiAgICAgIDwvc2FtbDpBdHRyaWJ1dGU+DQogICAgPC9zYW1sOkF0dHJpYnV0ZVN0YXRlbWVudD4NCiAgPC9zYW1sOkFzc2VydGlvbj4NCjwvc2FtbHA6UmVzcG9uc2U+
\ No newline at end of file
diff --git a/tests/data/responses/invalids/invalid_unpaired_inresponsesto.xml.base64 b/tests/data/responses/invalids/invalid_unpaired_inresponsesto.xml.base64
index 421ccd9f..bfd1a938 100644
--- a/tests/data/responses/invalids/invalid_unpaired_inresponsesto.xml.base64
+++ b/tests/data/responses/invalids/invalid_unpaired_inresponsesto.xml.base64
@@ -1 +1 @@
-PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c2FtbHA6UmVzcG9uc2UgeG1sbnM6c2FtbHA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgeG1sbnM6c2FtbD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9InBmeGMzMmFlZDY3LTgyMGYtNDI5Ni0wYzIwLTIwNWExMGRkNTc4NyIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDYtMTdUMTQ6NTQ6MTRaIiBEZXN0aW5hdGlvbj0iaHR0cDovL3N0dWZmLmNvbS9lbmRwb2ludHMvZW5kcG9pbnRzL2Fjcy5waHAiPg0KICA8c2FtbDpJc3N1ZXI+aHR0cDovL2lkcC5leGFtcGxlLmNvbS88L3NhbWw6SXNzdWVyPg0KICA8c2FtbHA6U3RhdHVzPg0KICAgIDxzYW1scDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz4NCiAgPC9zYW1scDpTdGF0dXM+DQogIDxzYW1sOkFzc2VydGlvbiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIElEPSJwZng3ODQxOTkxYy1jNzNmLTQwMzUtZTJlZS1jMTcwYzBlMWQzZTQiIFZlcnNpb249IjIuMCIgSXNzdWVJbnN0YW50PSIyMDExLTA2LTE3VDE0OjU0OjE0WiI+DQogICAgPHNhbWw6SXNzdWVyPmh0dHA6Ly9pZHAuZXhhbXBsZS5jb20vPC9zYW1sOklzc3Vlcj4gICAgDQogICAgPHNhbWw6U3ViamVjdD4NCiAgICAgIDxzYW1sOk5hbWVJRCBTUE5hbWVRdWFsaWZpZXI9ImhlbGxvLmNvbSIgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjE6bmFtZWlkLWZvcm1hdDplbWFpbEFkZHJlc3MiPnNvbWVvbmVAZXhhbXBsZS5jb208L3NhbWw6TmFtZUlEPg0KICAgICAgPHNhbWw6U3ViamVjdENvbmZpcm1hdGlvbiBNZXRob2Q9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpjbTpiZWFyZXIiPg0KICAgICAgICA8c2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uRGF0YSBOb3RPbk9yQWZ0ZXI9IjIwMjAtMDYtMTdUMTQ6NTk6MTRaIiBSZWNpcGllbnQ9Imh0dHA6Ly9zdHVmZi5jb20vZW5kcG9pbnRzL2VuZHBvaW50cy9hY3MucGhwIiBJblJlc3BvbnNlVG89ImludmFsaWRfaW5yZXNwb25zZSIvPg0KICAgICAgPC9zYW1sOlN1YmplY3RDb25maXJtYXRpb24+DQogICAgPC9zYW1sOlN1YmplY3Q+DQogICAgPHNhbWw6Q29uZGl0aW9ucyBOb3RCZWZvcmU9IjIwMTAtMDYtMTdUMTQ6NTM6NDRaIiBOb3RPbk9yQWZ0ZXI9IjIwMjEtMDYtMTdUMTQ6NTk6MTRaIj4NCiAgICAgIDxzYW1sOkF1ZGllbmNlUmVzdHJpY3Rpb24+DQogICAgICAgIDxzYW1sOkF1ZGllbmNlPmh0dHA6Ly9zdHVmZi5jb20vZW5kcG9pbnRzL21ldGFkYXRhLnBocDwvc2FtbDpBdWRpZW5jZT4NCiAgICAgIDwvc2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPg0KICAgIDwvc2FtbDpDb25kaXRpb25zPg0KICAgIDxzYW1sOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAxMS0wNi0xN1QxNDo1NDowN1oiIFNlc3Npb25Ob3RPbk9yQWZ0ZXI9IjIwMjEtMDYtMTdUMjI6NTQ6MTRaIiBTZXNzaW9uSW5kZXg9Il81MWJlMzc5NjVmZWI1NTc5ZDgwMzE0MTA3NjkzNmRjMmU5ZDFkOThlYmYiPg0KICAgICAgPHNhbWw6QXV0aG5Db250ZXh0Pg0KICAgICAgICA8c2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZDwvc2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj4NCiAgICAgIDwvc2FtbDpBdXRobkNvbnRleHQ+DQogICAgPC9zYW1sOkF1dGhuU3RhdGVtZW50Pg0KICAgIDxzYW1sOkF0dHJpYnV0ZVN0YXRlbWVudD4NCiAgICAgIDxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJtYWlsIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OmJhc2ljIj4NCiAgICAgICAgPHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+c29tZW9uZUBleGFtcGxlLmNvbTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT4NCiAgICAgIDwvc2FtbDpBdHRyaWJ1dGU+DQogICAgPC9zYW1sOkF0dHJpYnV0ZVN0YXRlbWVudD4NCiAgPC9zYW1sOkFzc2VydGlvbj4NCjwvc2FtbHA6UmVzcG9uc2U+
+PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c2FtbHA6UmVzcG9uc2UgeG1sbnM6c2FtbHA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgeG1sbnM6c2FtbD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9InBmeGMzMmFlZDY3LTgyMGYtNDI5Ni0wYzIwLTIwNWExMGRkNTc4NyIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDYtMTdUMTQ6NTQ6MTRaIiBEZXN0aW5hdGlvbj0iaHR0cDovL3N0dWZmLmNvbS9lbmRwb2ludHMvZW5kcG9pbnRzL2Fjcy5waHAiPg0KICA8c2FtbDpJc3N1ZXI+aHR0cDovL2lkcC5leGFtcGxlLmNvbS88L3NhbWw6SXNzdWVyPg0KICA8c2FtbHA6U3RhdHVzPg0KICAgIDxzYW1scDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz4NCiAgPC9zYW1scDpTdGF0dXM+DQogIDxzYW1sOkFzc2VydGlvbiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIElEPSJwZng3ODQxOTkxYy1jNzNmLTQwMzUtZTJlZS1jMTcwYzBlMWQzZTQiIFZlcnNpb249IjIuMCIgSXNzdWVJbnN0YW50PSIyMDExLTA2LTE3VDE0OjU0OjE0WiI+DQogICAgPHNhbWw6SXNzdWVyPmh0dHA6Ly9pZHAuZXhhbXBsZS5jb20vPC9zYW1sOklzc3Vlcj4gICAgDQogICAgPHNhbWw6U3ViamVjdD4NCiAgICAgIDxzYW1sOk5hbWVJRCBTUE5hbWVRdWFsaWZpZXI9ImhlbGxvLmNvbSIgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjE6bmFtZWlkLWZvcm1hdDplbWFpbEFkZHJlc3MiPnNvbWVvbmVAZXhhbXBsZS5jb208L3NhbWw6TmFtZUlEPg0KICAgICAgPHNhbWw6U3ViamVjdENvbmZpcm1hdGlvbiBNZXRob2Q9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpjbTpiZWFyZXIiPg0KICAgICAgICA8c2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uRGF0YSBOb3RPbk9yQWZ0ZXI9IjI5OTktMDYtMTdUMTQ6NTk6MTRaIiBSZWNpcGllbnQ9Imh0dHA6Ly9zdHVmZi5jb20vZW5kcG9pbnRzL2VuZHBvaW50cy9hY3MucGhwIiBJblJlc3BvbnNlVG89ImludmFsaWRfaW5yZXNwb25zZSIvPg0KICAgICAgPC9zYW1sOlN1YmplY3RDb25maXJtYXRpb24+DQogICAgPC9zYW1sOlN1YmplY3Q+DQogICAgPHNhbWw6Q29uZGl0aW9ucyBOb3RCZWZvcmU9IjIwMTAtMDYtMTdUMTQ6NTM6NDRaIiBOb3RPbk9yQWZ0ZXI9IjI5OTktMDYtMTdUMTQ6NTk6MTRaIj4NCiAgICAgIDxzYW1sOkF1ZGllbmNlUmVzdHJpY3Rpb24+DQogICAgICAgIDxzYW1sOkF1ZGllbmNlPmh0dHA6Ly9zdHVmZi5jb20vZW5kcG9pbnRzL21ldGFkYXRhLnBocDwvc2FtbDpBdWRpZW5jZT4NCiAgICAgIDwvc2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPg0KICAgIDwvc2FtbDpDb25kaXRpb25zPg0KICAgIDxzYW1sOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAxMS0wNi0xN1QxNDo1NDowN1oiIFNlc3Npb25Ob3RPbk9yQWZ0ZXI9IjI5OTktMDYtMTdUMjI6NTQ6MTRaIiBTZXNzaW9uSW5kZXg9Il81MWJlMzc5NjVmZWI1NTc5ZDgwMzE0MTA3NjkzNmRjMmU5ZDFkOThlYmYiPg0KICAgICAgPHNhbWw6QXV0aG5Db250ZXh0Pg0KICAgICAgICA8c2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZDwvc2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj4NCiAgICAgIDwvc2FtbDpBdXRobkNvbnRleHQ+DQogICAgPC9zYW1sOkF1dGhuU3RhdGVtZW50Pg0KICAgIDxzYW1sOkF0dHJpYnV0ZVN0YXRlbWVudD4NCiAgICAgIDxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJtYWlsIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OmJhc2ljIj4NCiAgICAgICAgPHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+c29tZW9uZUBleGFtcGxlLmNvbTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT4NCiAgICAgIDwvc2FtbDpBdHRyaWJ1dGU+DQogICAgPC9zYW1sOkF0dHJpYnV0ZVN0YXRlbWVudD4NCiAgPC9zYW1sOkFzc2VydGlvbj4NCjwvc2FtbHA6UmVzcG9uc2U+
\ No newline at end of file
diff --git a/tests/data/responses/unsigned_response.xml.base64 b/tests/data/responses/unsigned_response.xml.base64
index 66892b53..09ea69c7 100644
--- a/tests/data/responses/unsigned_response.xml.base64
+++ b/tests/data/responses/unsigned_response.xml.base64
@@ -1 +1 @@
-PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c2FtbHA6UmVzcG9uc2UgeG1sbnM6c2FtbHA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgeG1sbnM6c2FtbD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9InBmeGMzMmFlZDY3LTgyMGYtNDI5Ni0wYzIwLTIwNWExMGRkNTc4NyIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDYtMTdUMTQ6NTQ6MTRaIiBEZXN0aW5hdGlvbj0iaHR0cDovL3N0dWZmLmNvbS9lbmRwb2ludHMvZW5kcG9pbnRzL2Fjcy5waHAiIEluUmVzcG9uc2VUbz0iXzU3YmNiZjcwLTdiMWYtMDEyZS1jODIxLTc4MmJjYjEzYmIzOCI+DQogIDxzYW1sOklzc3Vlcj5odHRwOi8vaWRwLmV4YW1wbGUuY29tLzwvc2FtbDpJc3N1ZXI+DQogIDxzYW1scDpTdGF0dXM+DQogICAgPHNhbWxwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPg0KICA8L3NhbWxwOlN0YXR1cz4NCiAgPHNhbWw6QXNzZXJ0aW9uIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhtbG5zOnhzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIgSUQ9InBmeDc4NDE5OTFjLWM3M2YtNDAzNS1lMmVlLWMxNzBjMGUxZDNlNCIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDYtMTdUMTQ6NTQ6MTRaIj4NCiAgICA8c2FtbDpJc3N1ZXI+aHR0cDovL2lkcC5leGFtcGxlLmNvbS88L3NhbWw6SXNzdWVyPiAgICANCiAgICA8c2FtbDpTdWJqZWN0Pg0KICAgICAgPHNhbWw6TmFtZUlEIFNQTmFtZVF1YWxpZmllcj0iaGVsbG8uY29tIiBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjEuMTpuYW1laWQtZm9ybWF0OmVtYWlsQWRkcmVzcyI+c29tZW9uZUBleGFtcGxlLmNvbTwvc2FtbDpOYW1lSUQ+DQogICAgICA8c2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uIE1ldGhvZD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmNtOmJlYXJlciI+DQogICAgICAgIDxzYW1sOlN1YmplY3RDb25maXJtYXRpb25EYXRhIE5vdE9uT3JBZnRlcj0iMjAyMC0wNi0xN1QxNDo1OToxNFoiIFJlY2lwaWVudD0iaHR0cDovL3N0dWZmLmNvbS9lbmRwb2ludHMvZW5kcG9pbnRzL2Fjcy5waHAiIEluUmVzcG9uc2VUbz0iXzU3YmNiZjcwLTdiMWYtMDEyZS1jODIxLTc4MmJjYjEzYmIzOCIvPg0KICAgICAgPC9zYW1sOlN1YmplY3RDb25maXJtYXRpb24+DQogICAgPC9zYW1sOlN1YmplY3Q+DQogICAgPHNhbWw6Q29uZGl0aW9ucyBOb3RCZWZvcmU9IjIwMTAtMDYtMTdUMTQ6NTM6NDRaIiBOb3RPbk9yQWZ0ZXI9IjIwMjEtMDYtMTdUMTQ6NTk6MTRaIj4NCiAgICAgIDxzYW1sOkF1ZGllbmNlUmVzdHJpY3Rpb24+DQogICAgICAgIDxzYW1sOkF1ZGllbmNlPmh0dHA6Ly9zdHVmZi5jb20vZW5kcG9pbnRzL21ldGFkYXRhLnBocDwvc2FtbDpBdWRpZW5jZT4NCiAgICAgIDwvc2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPg0KICAgIDwvc2FtbDpDb25kaXRpb25zPg0KICAgIDxzYW1sOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAxMS0wNi0xN1QxNDo1NDowN1oiIFNlc3Npb25Ob3RPbk9yQWZ0ZXI9IjIwMjEtMDYtMTdUMjI6NTQ6MTRaIiBTZXNzaW9uSW5kZXg9Il81MWJlMzc5NjVmZWI1NTc5ZDgwMzE0MTA3NjkzNmRjMmU5ZDFkOThlYmYiPg0KICAgICAgPHNhbWw6QXV0aG5Db250ZXh0Pg0KICAgICAgICA8c2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZDwvc2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj4NCiAgICAgIDwvc2FtbDpBdXRobkNvbnRleHQ+DQogICAgPC9zYW1sOkF1dGhuU3RhdGVtZW50Pg0KICAgIDxzYW1sOkF0dHJpYnV0ZVN0YXRlbWVudD4NCiAgICAgIDxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJtYWlsIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OmJhc2ljIj4NCiAgICAgICAgPHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+c29tZW9uZUBleGFtcGxlLmNvbTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT4NCiAgICAgIDwvc2FtbDpBdHRyaWJ1dGU+DQogICAgPC9zYW1sOkF0dHJpYnV0ZVN0YXRlbWVudD4NCiAgPC9zYW1sOkFzc2VydGlvbj4NCjwvc2FtbHA6UmVzcG9uc2U+
+PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c2FtbHA6UmVzcG9uc2UgeG1sbnM6c2FtbHA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgeG1sbnM6c2FtbD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9InBmeGMzMmFlZDY3LTgyMGYtNDI5Ni0wYzIwLTIwNWExMGRkNTc4NyIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDYtMTdUMTQ6NTQ6MTRaIiBEZXN0aW5hdGlvbj0iaHR0cDovL3N0dWZmLmNvbS9lbmRwb2ludHMvZW5kcG9pbnRzL2Fjcy5waHAiIEluUmVzcG9uc2VUbz0iXzU3YmNiZjcwLTdiMWYtMDEyZS1jODIxLTc4MmJjYjEzYmIzOCI+DQogIDxzYW1sOklzc3Vlcj5odHRwOi8vaWRwLmV4YW1wbGUuY29tLzwvc2FtbDpJc3N1ZXI+DQogIDxzYW1scDpTdGF0dXM+DQogICAgPHNhbWxwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPg0KICA8L3NhbWxwOlN0YXR1cz4NCiAgPHNhbWw6QXNzZXJ0aW9uIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhtbG5zOnhzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIgSUQ9InBmeDc4NDE5OTFjLWM3M2YtNDAzNS1lMmVlLWMxNzBjMGUxZDNlNCIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDYtMTdUMTQ6NTQ6MTRaIj4NCiAgICA8c2FtbDpJc3N1ZXI+aHR0cDovL2lkcC5leGFtcGxlLmNvbS88L3NhbWw6SXNzdWVyPiAgICANCiAgICA8c2FtbDpTdWJqZWN0Pg0KICAgICAgPHNhbWw6TmFtZUlEIFNQTmFtZVF1YWxpZmllcj0iaGVsbG8uY29tIiBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjEuMTpuYW1laWQtZm9ybWF0OmVtYWlsQWRkcmVzcyI+c29tZW9uZUBleGFtcGxlLmNvbTwvc2FtbDpOYW1lSUQ+DQogICAgICA8c2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uIE1ldGhvZD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmNtOmJlYXJlciI+DQogICAgICAgIDxzYW1sOlN1YmplY3RDb25maXJtYXRpb25EYXRhIE5vdE9uT3JBZnRlcj0iMjk5OS0wNi0xN1QxNDo1OToxNFoiIFJlY2lwaWVudD0iaHR0cDovL3N0dWZmLmNvbS9lbmRwb2ludHMvZW5kcG9pbnRzL2Fjcy5waHAiIEluUmVzcG9uc2VUbz0iXzU3YmNiZjcwLTdiMWYtMDEyZS1jODIxLTc4MmJjYjEzYmIzOCIvPg0KICAgICAgPC9zYW1sOlN1YmplY3RDb25maXJtYXRpb24+DQogICAgPC9zYW1sOlN1YmplY3Q+DQogICAgPHNhbWw6Q29uZGl0aW9ucyBOb3RCZWZvcmU9IjIwMTAtMDYtMTdUMTQ6NTM6NDRaIiBOb3RPbk9yQWZ0ZXI9IjI5OTktMDYtMTdUMTQ6NTk6MTRaIj4NCiAgICAgIDxzYW1sOkF1ZGllbmNlUmVzdHJpY3Rpb24+DQogICAgICAgIDxzYW1sOkF1ZGllbmNlPmh0dHA6Ly9zdHVmZi5jb20vZW5kcG9pbnRzL21ldGFkYXRhLnBocDwvc2FtbDpBdWRpZW5jZT4NCiAgICAgIDwvc2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPg0KICAgIDwvc2FtbDpDb25kaXRpb25zPg0KICAgIDxzYW1sOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAxMS0wNi0xN1QxNDo1NDowN1oiIFNlc3Npb25Ob3RPbk9yQWZ0ZXI9IjI5OTktMDYtMTdUMjI6NTQ6MTRaIiBTZXNzaW9uSW5kZXg9Il81MWJlMzc5NjVmZWI1NTc5ZDgwMzE0MTA3NjkzNmRjMmU5ZDFkOThlYmYiPg0KICAgICAgPHNhbWw6QXV0aG5Db250ZXh0Pg0KICAgICAgICA8c2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZDwvc2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj4NCiAgICAgIDwvc2FtbDpBdXRobkNvbnRleHQ+DQogICAgPC9zYW1sOkF1dGhuU3RhdGVtZW50Pg0KICAgIDxzYW1sOkF0dHJpYnV0ZVN0YXRlbWVudD4NCiAgICAgIDxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJtYWlsIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OmJhc2ljIj4NCiAgICAgICAgPHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+c29tZW9uZUBleGFtcGxlLmNvbTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT4NCiAgICAgIDwvc2FtbDpBdHRyaWJ1dGU+DQogICAgPC9zYW1sOkF0dHJpYnV0ZVN0YXRlbWVudD4NCiAgPC9zYW1sOkFzc2VydGlvbj4NCjwvc2FtbHA6UmVzcG9uc2U+
\ No newline at end of file
diff --git a/tests/data/responses/unsigned_response_with_miliseconds.xm.base64 b/tests/data/responses/unsigned_response_with_miliseconds.xm.base64
index 76522b7e..b3bc8fce 100644
--- a/tests/data/responses/unsigned_response_with_miliseconds.xm.base64
+++ b/tests/data/responses/unsigned_response_with_miliseconds.xm.base64
@@ -1 +1 @@
-PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c2FtbHA6UmVzcG9uc2UgeG1sbnM6c2FtbHA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgeG1sbnM6c2FtbD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9InBmeGMzMmFlZDY3LTgyMGYtNDI5Ni0wYzIwLTIwNWExMGRkNTc4NyIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDYtMTdUMTQ6NTQ6MTQuMTIwWiIgRGVzdGluYXRpb249Imh0dHA6Ly9zdHVmZi5jb20vZW5kcG9pbnRzL2VuZHBvaW50cy9hY3MucGhwIiBJblJlc3BvbnNlVG89Il81N2JjYmY3MC03YjFmLTAxMmUtYzgyMS03ODJiY2IxM2JiMzgiPg0KICA8c2FtbDpJc3N1ZXI+aHR0cDovL2lkcC5leGFtcGxlLmNvbS88L3NhbWw6SXNzdWVyPg0KICA8c2FtbHA6U3RhdHVzPg0KICAgIDxzYW1scDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz4NCiAgPC9zYW1scDpTdGF0dXM+DQogIDxzYW1sOkFzc2VydGlvbiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIElEPSJwZng3ODQxOTkxYy1jNzNmLTQwMzUtZTJlZS1jMTcwYzBlMWQzZTQiIFZlcnNpb249IjIuMCIgSXNzdWVJbnN0YW50PSIyMDExLTA2LTE3VDE0OjU0OjE0LjEyMFoiPg0KICAgIDxzYW1sOklzc3Vlcj5odHRwOi8vaWRwLmV4YW1wbGUuY29tLzwvc2FtbDpJc3N1ZXI+ICAgIA0KICAgIDxzYW1sOlN1YmplY3Q+DQogICAgICA8c2FtbDpOYW1lSUQgU1BOYW1lUXVhbGlmaWVyPSJoZWxsby5jb20iIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4xOm5hbWVpZC1mb3JtYXQ6ZW1haWxBZGRyZXNzIj5zb21lb25lQGV4YW1wbGUuY29tPC9zYW1sOk5hbWVJRD4NCiAgICAgIDxzYW1sOlN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj4NCiAgICAgICAgPHNhbWw6U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgTm90T25PckFmdGVyPSIyMDIwLTA2LTE3VDE0OjU5OjE0WiIgUmVjaXBpZW50PSJodHRwOi8vc3R1ZmYuY29tL2VuZHBvaW50cy9lbmRwb2ludHMvYWNzLnBocCIgSW5SZXNwb25zZVRvPSJfNTdiY2JmNzAtN2IxZi0wMTJlLWM4MjEtNzgyYmNiMTNiYjM4Ii8+DQogICAgICA8L3NhbWw6U3ViamVjdENvbmZpcm1hdGlvbj4NCiAgICA8L3NhbWw6U3ViamVjdD4NCiAgICA8c2FtbDpDb25kaXRpb25zIE5vdEJlZm9yZT0iMjAxMC0wNi0xN1QxNDo1Mzo0NC4xNzNaIiBOb3RPbk9yQWZ0ZXI9IjIwMjEtMDYtMTdUMTQ6NTk6MTQuMjM1WiI+DQogICAgICA8c2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPg0KICAgICAgICA8c2FtbDpBdWRpZW5jZT5odHRwOi8vc3R1ZmYuY29tL2VuZHBvaW50cy9tZXRhZGF0YS5waHA8L3NhbWw6QXVkaWVuY2U+DQogICAgICA8L3NhbWw6QXVkaWVuY2VSZXN0cmljdGlvbj4NCiAgICA8L3NhbWw6Q29uZGl0aW9ucz4NCiAgICA8c2FtbDpBdXRoblN0YXRlbWVudCBBdXRobkluc3RhbnQ9IjIwMTEtMDYtMTdUMTQ6NTQ6MDcuMTIwWiIgU2Vzc2lvbk5vdE9uT3JBZnRlcj0iMjAyMS0wNi0xN1QyMjo1NDoxNC4xMjBaIiBTZXNzaW9uSW5kZXg9Il81MWJlMzc5NjVmZWI1NTc5ZDgwMzE0MTA3NjkzNmRjMmU5ZDFkOThlYmYiPg0KICAgICAgPHNhbWw6QXV0aG5Db250ZXh0Pg0KICAgICAgICA8c2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZDwvc2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj4NCiAgICAgIDwvc2FtbDpBdXRobkNvbnRleHQ+DQogICAgPC9zYW1sOkF1dGhuU3RhdGVtZW50Pg0KICAgIDxzYW1sOkF0dHJpYnV0ZVN0YXRlbWVudD4NCiAgICAgIDxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJtYWlsIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OmJhc2ljIj4NCiAgICAgICAgPHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+c29tZW9uZUBleGFtcGxlLmNvbTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT4NCiAgICAgIDwvc2FtbDpBdHRyaWJ1dGU+DQogICAgPC9zYW1sOkF0dHJpYnV0ZVN0YXRlbWVudD4NCiAgPC9zYW1sOkFzc2VydGlvbj4NCjwvc2FtbHA6UmVzcG9uc2U+
\ No newline at end of file
+PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c2FtbHA6UmVzcG9uc2UgeG1sbnM6c2FtbHA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgeG1sbnM6c2FtbD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9InBmeGMzMmFlZDY3LTgyMGYtNDI5Ni0wYzIwLTIwNWExMGRkNTc4NyIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDYtMTdUMTQ6NTQ6MTQuMTIwWiIgRGVzdGluYXRpb249Imh0dHA6Ly9zdHVmZi5jb20vZW5kcG9pbnRzL2VuZHBvaW50cy9hY3MucGhwIiBJblJlc3BvbnNlVG89Il81N2JjYmY3MC03YjFmLTAxMmUtYzgyMS03ODJiY2IxM2JiMzgiPg0KICA8c2FtbDpJc3N1ZXI+aHR0cDovL2lkcC5leGFtcGxlLmNvbS88L3NhbWw6SXNzdWVyPg0KICA8c2FtbHA6U3RhdHVzPg0KICAgIDxzYW1scDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz4NCiAgPC9zYW1scDpTdGF0dXM+DQogIDxzYW1sOkFzc2VydGlvbiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIElEPSJwZng3ODQxOTkxYy1jNzNmLTQwMzUtZTJlZS1jMTcwYzBlMWQzZTQiIFZlcnNpb249IjIuMCIgSXNzdWVJbnN0YW50PSIyMDExLTA2LTE3VDE0OjU0OjE0LjEyMFoiPg0KICAgIDxzYW1sOklzc3Vlcj5odHRwOi8vaWRwLmV4YW1wbGUuY29tLzwvc2FtbDpJc3N1ZXI+ICAgIA0KICAgIDxzYW1sOlN1YmplY3Q+DQogICAgICA8c2FtbDpOYW1lSUQgU1BOYW1lUXVhbGlmaWVyPSJoZWxsby5jb20iIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4xOm5hbWVpZC1mb3JtYXQ6ZW1haWxBZGRyZXNzIj5zb21lb25lQGV4YW1wbGUuY29tPC9zYW1sOk5hbWVJRD4NCiAgICAgIDxzYW1sOlN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj4NCiAgICAgICAgPHNhbWw6U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgTm90T25PckFmdGVyPSIyOTk5LTA2LTE3VDE0OjU5OjE0WiIgUmVjaXBpZW50PSJodHRwOi8vc3R1ZmYuY29tL2VuZHBvaW50cy9lbmRwb2ludHMvYWNzLnBocCIgSW5SZXNwb25zZVRvPSJfNTdiY2JmNzAtN2IxZi0wMTJlLWM4MjEtNzgyYmNiMTNiYjM4Ii8+DQogICAgICA8L3NhbWw6U3ViamVjdENvbmZpcm1hdGlvbj4NCiAgICA8L3NhbWw6U3ViamVjdD4NCiAgICA8c2FtbDpDb25kaXRpb25zIE5vdEJlZm9yZT0iMjAxMC0wNi0xN1QxNDo1Mzo0NC4xNzNaIiBOb3RPbk9yQWZ0ZXI9IjI5OTktMDYtMTdUMTQ6NTk6MTQuMjM1WiI+DQogICAgICA8c2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPg0KICAgICAgICA8c2FtbDpBdWRpZW5jZT5odHRwOi8vc3R1ZmYuY29tL2VuZHBvaW50cy9tZXRhZGF0YS5waHA8L3NhbWw6QXVkaWVuY2U+DQogICAgICA8L3NhbWw6QXVkaWVuY2VSZXN0cmljdGlvbj4NCiAgICA8L3NhbWw6Q29uZGl0aW9ucz4NCiAgICA8c2FtbDpBdXRoblN0YXRlbWVudCBBdXRobkluc3RhbnQ9IjIwMTEtMDYtMTdUMTQ6NTQ6MDcuMTIwWiIgU2Vzc2lvbk5vdE9uT3JBZnRlcj0iMjk5OS0wNi0xN1QyMjo1NDoxNC4xMjBaIiBTZXNzaW9uSW5kZXg9Il81MWJlMzc5NjVmZWI1NTc5ZDgwMzE0MTA3NjkzNmRjMmU5ZDFkOThlYmYiPg0KICAgICAgPHNhbWw6QXV0aG5Db250ZXh0Pg0KICAgICAgICA8c2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZDwvc2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj4NCiAgICAgIDwvc2FtbDpBdXRobkNvbnRleHQ+DQogICAgPC9zYW1sOkF1dGhuU3RhdGVtZW50Pg0KICAgIDxzYW1sOkF0dHJpYnV0ZVN0YXRlbWVudD4NCiAgICAgIDxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJtYWlsIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OmJhc2ljIj4NCiAgICAgICAgPHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+c29tZW9uZUBleGFtcGxlLmNvbTwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT4NCiAgICAgIDwvc2FtbDpBdHRyaWJ1dGU+DQogICAgPC9zYW1sOkF0dHJpYnV0ZVN0YXRlbWVudD4NCiAgPC9zYW1sOkFzc2VydGlvbj4NCjwvc2FtbHA6UmVzcG9uc2U+
\ No newline at end of file
diff --git a/tests/src/OneLogin/Saml2/AuthTest.php b/tests/src/OneLogin/Saml2/AuthTest.php
index e6193207..c85a2309 100644
--- a/tests/src/OneLogin/Saml2/AuthTest.php
+++ b/tests/src/OneLogin/Saml2/AuthTest.php
@@ -95,7 +95,7 @@ public function testGetSLOurl()
/**
* Tests the getSLOResponseUrl method of the Auth class
*
- * @covers OneLogin\Saml2\Auth::getSLOurl
+ * @covers OneLogin\Saml2\Auth::getSLOResponseUrl
*/
public function testGetSLOResponseUrl()
{
diff --git a/tests/src/OneLogin/Saml2/ResponseTest.php b/tests/src/OneLogin/Saml2/ResponseTest.php
index adbfc692..ab0da70e 100644
--- a/tests/src/OneLogin/Saml2/ResponseTest.php
+++ b/tests/src/OneLogin/Saml2/ResponseTest.php
@@ -631,6 +631,14 @@ public function testGetAttributes()
} catch (ValidationError $e) {
$this->assertContains('Found an Attribute element with duplicated Name', $e->getMessage());
}
+
+ $settingsDir = TEST_ROOT .'/settings/';
+ include $settingsDir.'settings1.php';
+ $settingsInfo['security']['allowRepeatAttributeName'] = true;
+ $settings2 = new Settings($settingsInfo);
+ $response5 = new Response($settings2, $xml4);
+ $attrs = $response5->getAttributes();
+ $this->assertEquals([0 => "test", 1 => "test2"], $attrs['uid']);
}
/**
diff --git a/tests/src/OneLogin/Saml2/SettingsTest.php b/tests/src/OneLogin/Saml2/SettingsTest.php
index df323b7c..e3061bff 100644
--- a/tests/src/OneLogin/Saml2/SettingsTest.php
+++ b/tests/src/OneLogin/Saml2/SettingsTest.php
@@ -403,6 +403,66 @@ public function testCheckSettings()
}
}
+ /**
+ * Tests the getIdPSSOurl method of the Settings class
+ *
+ * @covers OneLogin\Saml2\Settings::getIdPSSOurl
+ */
+ public function testGetIdPSSOurl()
+ {
+ $settingsDir = TEST_ROOT .'/settings/';
+ include $settingsDir.'settings1.php';
+
+ $settings = new Settings($settingsInfo);
+
+ $ssoUrl = "http://idp.example.com/SSOService.php";
+ $this->assertEquals($settings->getIdPSSOUrl(), $ssoUrl);
+ }
+
+ /**
+ * Tests the getIdPSLOurl method of the Settings class
+ *
+ * @covers OneLogin\Saml2\Settings::getIdPSLOurl
+ */
+ public function testGetIdPSLOurl()
+ {
+ $settingsDir = TEST_ROOT .'/settings/';
+ include $settingsDir.'settings1.php';
+
+ $settings = new Settings($settingsInfo);
+
+ $sloUrl = "http://idp.example.com/SingleLogoutService.php";
+ $this->assertEquals($settings->getIdPSLOUrl(), $sloUrl);
+
+ include $settingsDir.'settings2.php';
+ $settings2 = new Settings($settingsInfo);
+
+ $sloUrl = "http://idp.example.com/SingleLogoutService.php";
+ $this->assertEquals($settings2->getIdPSLOUrl(), $sloUrl);
+ }
+
+ /**
+ * Tests the getIdPSLOResponseUrl method of the Settings class
+ *
+ * @covers OneLogin\Saml2\Settings::getIdPSLOResponseUrl
+ */
+ public function testGetIdPSLOResponseUrl()
+ {
+ $settingsDir = TEST_ROOT .'/settings/';
+ include $settingsDir.'settings1.php';
+
+ $settings = new Settings($settingsInfo);
+
+ $sloUrl = "http://idp.example.com/SingleLogoutServiceResponse.php";
+ $this->assertEquals($settings->getIdPSLOResponseUrl(), $sloUrl);
+
+ include $settingsDir.'settings2.php';
+ $settings2 = new Settings($settingsInfo);
+
+ $sloUrl = "http://idp.example.com/SingleLogoutService.php";
+ $this->assertEquals($settings2->getIdPSLOUrl(), $sloUrl);
+ }
+
/**
* Tests the getSPMetadata method of the Settings
* Case unsigned metadata
diff --git a/tests/src/OneLogin/Saml2/UtilsTest.php b/tests/src/OneLogin/Saml2/UtilsTest.php
index 47800a4f..e353cb89 100644
--- a/tests/src/OneLogin/Saml2/UtilsTest.php
+++ b/tests/src/OneLogin/Saml2/UtilsTest.php
@@ -370,10 +370,10 @@ public function testGetselfhost()
public function testisHTTPS()
{
$this->assertFalse(Utils::isHTTPS());
-
+
$_SERVER['HTTPS'] = 'on';
$this->assertTrue(Utils::isHTTPS());
-
+
unset($_SERVER['HTTPS']);
$this->assertFalse(Utils::isHTTPS());
$_SERVER['HTTP_HOST'] = 'example.com:443';
@@ -497,7 +497,7 @@ public function testSetBaseURL()
$expectedUrlNQ2 = 'http://anothersp.example.com:81/example2/route.php';
$expectedRoutedUrlNQ2 = 'http://anothersp.example.com:81/example2/route.php';
$expectedUrl2 = 'http://anothersp.example.com:81/example2/route.php?x=test';
-
+
$this->assertEquals('http', Utils::getSelfProtocol());
$this->assertEquals('anothersp.example.com', Utils::getSelfHost());
$this->assertEquals('81', Utils::getSelfPort());
@@ -853,6 +853,21 @@ public function testGenerateNameIdWithSPNameQualifier()
$nameidExpectedEnc = '';
$this->assertContains($nameidExpectedEnc, $nameIdEnc);
+
+ // Check AES128_GCM support
+ if (version_compare(phpversion(), '7.1.0', '>=') && in_array("aes-128-gcm", openssl_get_cipher_methods())) {
+ $nameidExpectedEnc = '';
+
+ $nameIdEnc = Utils::generateNameId(
+ $nameIdValue,
+ $entityId,
+ $nameIDFormat,
+ $key,
+ null,
+ XMLSecurityKey::AES128_GCM
+ );
+ $this->assertContains($nameidExpectedEnc, $nameIdEnc);
+ }
}
/**
@@ -933,7 +948,7 @@ public function testDeleteLocalSession()
$this->assertTrue($_SESSION['samltest']);
Utils::deleteLocalSession();
- $this->assertFalse(isset($_SESSION));
+ $this->assertEmpty($_SESSION);
$this->assertFalse(isset($_SESSION['samltest']));
$prev = error_reporting(0);
@@ -942,7 +957,7 @@ public function testDeleteLocalSession()
$_SESSION['samltest'] = true;
Utils::deleteLocalSession();
- $this->assertFalse(isset($_SESSION));
+ $this->assertEmpty($_SESSION);
$this->assertFalse(isset($_SESSION['samltest']));
}
}