/**
* Checks if the Logout Request recieved is valid.
*
* @return boolean If the Logout Request is or not valid
*/
public function isValid($retrieveParametersFromServer = false)
{
$this->_error = null;
try {
$dom = new DOMDocument();
$dom = OneLogin_Saml2_Utils::loadXML($dom, $this->_logoutRequest);
$idpData = $this->_settings->getIdPData();
$idPEntityId = $idpData['entityId'];
if ($this->_settings->isStrict()) {
$security = $this->_settings->getSecurityData();
if ($security['wantXMLValidation']) {
$res = OneLogin_Saml2_Utils::validateXML($dom, 'saml-schema-protocol-2.0.xsd', $this->_settings->isDebugActive());
if (!$res instanceof DOMDocument) {
throw new Exception("Invalid SAML Logout Request. Not match the saml-schema-protocol-2.0.xsd");
}
}
$currentURL = OneLogin_Saml2_Utils::getSelfRoutedURLNoQuery();
// Check NotOnOrAfter
if ($dom->documentElement->hasAttribute('NotOnOrAfter')) {
$na = OneLogin_Saml2_Utils::parseSAML2Time($dom->documentElement->getAttribute('NotOnOrAfter'));
if ($na <= time()) {
throw new Exception('Timing issues (please check your clock settings)');
}
}
// Check destination
if ($dom->documentElement->hasAttribute('Destination')) {
$destination = $dom->documentElement->getAttribute('Destination');
if (!empty($destination)) {
if (strpos($destination, $currentURL) === false) {
throw new Exception("The LogoutRequest was received at {$currentURL} instead of {$destination}");
}
}
}
$nameId = $this->getNameId($dom, $this->_settings->getSPkey());
// Check issuer
$issuer = $this->getIssuer($dom);
if (!empty($issuer) && $issuer != $idPEntityId) {
throw new Exception("Invalid issuer in the Logout Request");
}
if ($security['wantMessagesSigned']) {
if (!isset($_GET['Signature'])) {
throw new Exception("The Message of the Logout Request is not signed and the SP require it");
}
}
}
if (isset($_GET['Signature'])) {
if (!isset($_GET['SigAlg'])) {
$signAlg = XMLSecurityKey::RSA_SHA1;
} else {
$signAlg = $_GET['SigAlg'];
}
if ($retrieveParametersFromServer) {
$signedQuery = 'SAMLRequest=' . OneLogin_Saml2_Utils::extractOriginalQueryParam('SAMLRequest');
if (isset($_GET['RelayState'])) {
$signedQuery .= '&RelayState=' . OneLogin_Saml2_Utils::extractOriginalQueryParam('RelayState');
}
$signedQuery .= '&SigAlg=' . OneLogin_Saml2_Utils::extractOriginalQueryParam('SigAlg');
} else {
$signedQuery = 'SAMLRequest=' . urlencode($_GET['SAMLRequest']);
if (isset($_GET['RelayState'])) {
$signedQuery .= '&RelayState=' . urlencode($_GET['RelayState']);
}
$signedQuery .= '&SigAlg=' . urlencode($signAlg);
}
if (!isset($idpData['x509cert']) || empty($idpData['x509cert'])) {
throw new Exception('In order to validate the sign on the Logout Request, the x509cert of the IdP is required');
}
$cert = $idpData['x509cert'];
$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'public'));
$objKey->loadKey($cert, false, true);
if ($signAlg != XMLSecurityKey::RSA_SHA1) {
try {
$objKey = OneLogin_Saml2_Utils::castKey($objKey, $signAlg, 'public');
} catch (Exception $e) {
throw new Exception('Invalid signAlg in the recieved Logout Request');
}
}
if (!$objKey->verifySignature($signedQuery, base64_decode($_GET['Signature']))) {
throw new Exception('Signature validation failed. Logout Request rejected');
}
}
return true;
} catch (Exception $e) {
$this->_error = $e->getMessage();
$debug = $this->_settings->isDebugActive();
if ($debug) {
echo $this->_error;
}
return false;
}
}