_settings = $settings; $this->_document = clone $response->document; } /** * Verify that the document only contains a single Assertion * * @return bool TRUE if the document passes. */ public function validateNumAssertions() { $rootNode = $this->_document; $assertionNodes = $rootNode->getElementsByTagName('Assertion'); return ($assertionNodes->length == 1); } /** * Verify that the document is still valid according * * @return bool */ public function validateTimestamps() { $rootNode = $this->_document; $timestampNodes = $rootNode->getElementsByTagName('Conditions'); for ($i = 0; $i < $timestampNodes->length; $i++) { $nbAttribute = $timestampNodes->item($i)->attributes->getNamedItem("NotBefore"); $naAttribute = $timestampNodes->item($i)->attributes->getNamedItem("NotOnOrAfter"); if ($nbAttribute && strtotime($nbAttribute->textContent) > time()) { return false; } if ($naAttribute && strtotime($naAttribute->textContent) <= time()) { return false; } } return true; } /** * @return bool * * @throws Exception */ public function isValid() { $singleAssertion = $this->validateNumAssertions(); if (!$singleAssertion) { throw new Exception('Multiple assertions are not supported'); } $validTimestamps = $this->validateTimestamps(); if (!$validTimestamps) { throw new Exception('Timing issues (please check your clock settings)'); } $objXMLSecDSig = new XMLSecurityDSig(); $objDSig = $objXMLSecDSig->locateSignature($this->_document); if (!$objDSig) { throw new Exception('Cannot locate Signature Node'); } $objXMLSecDSig->canonicalizeSignedInfo(); $objXMLSecDSig->idKeys = array('ID'); $objKey = $objXMLSecDSig->locateKey(); if (!$objKey) { throw new Exception('We have no idea about the key'); } try { $objXMLSecDSig->validateReference(); } catch (Exception $e) { throw new Exception('Reference Validation Failed'); } XMLSecEnc::staticLocateKeyInfo($objKey, $objDSig); $objKey->loadKey($this->_settings->idpPublicCertificate, false, true); return ($objXMLSecDSig->verify($objKey) === 1); } }