public function validate(SAML2_Response $response, SAML2_Response_Validation_Result $result) { if (!$response->isSuccess()) { $result->addError($this->buildMessage($response->getStatus())); } }
/** * Process a response message. * * If the response is an error response, we will throw a sspmod_saml_Error * exception with the error. * * @param SimpleSAML_Configuration $spMetadata The metadata of the service provider. * @param SimpleSAML_Configuration $idpMetadata The metadata of the identity provider. * @param SAML2_Response $response The response. * @return array Array with SAML2_Assertion objects, containing valid assertions from the response. */ public static function processResponse(SimpleSAML_Configuration $spMetadata, SimpleSAML_Configuration $idpMetadata, SAML2_Response $response) { if (!$response->isSuccess()) { throw self::getResponseError($response); } /* Validate Response-element destination. */ $currentURL = \SimpleSAML\Utils\HTTP::getSelfURLNoQuery(); $msgDestination = $response->getDestination(); if ($msgDestination !== NULL && $msgDestination !== $currentURL) { throw new Exception('Destination in response doesn\'t match the current URL. Destination is "' . $msgDestination . '", current URL is "' . $currentURL . '".'); } $responseSigned = self::checkSign($idpMetadata, $response); /* * When we get this far, the response itself is valid. * We only need to check signatures and conditions of the response. */ $assertion = $response->getAssertions(); if (empty($assertion)) { throw new SimpleSAML_Error_Exception('No assertions found in response from IdP.'); } $ret = array(); foreach ($assertion as $a) { $ret[] = self::processAssertion($spMetadata, $idpMetadata, $response, $a, $responseSigned); } return $ret; }
/** * Process a response message. * * If the response is an error response, we will throw a sspmod_saml2_Error * exception with the error. * * @param SimpleSAML_Configuration $spMetadata The metadata of the service provider. * @param SimpleSAML_Configuration $idpMetadata The metadata of the identity provider. * @param SAML2_Response $response The response. * @return SAML2_Assertion The assertion in the response, if it is valid. */ public static function processResponse(SimpleSAML_Configuration $spMetadata, SimpleSAML_Configuration $idpMetadata, SAML2_Response $response) { if (!$response->isSuccess()) { throw self::getResponseError($response); } /* * When we get this far, the response itself is valid. * We only need to check signatures and conditions of the response. */ $assertion = $response->getAssertions(); if (empty($assertion)) { throw new SimpleSAML_Error_Exception('No assertions found in response from IdP.'); } elseif (count($assertion) > 1) { throw new SimpleSAML_Error_Exception('More than one assertion found in response from IdP.'); } $assertion = $assertion[0]; $assertion = self::decryptAssertion($idpMetadata, $spMetadata, $assertion); if (!self::checkSign($idpMetadata, $assertion)) { if (!self::checkSign($idpMetadata, $response)) { throw new SimpleSAML_Error_Exception('Neither the assertion nor the response was signed.'); } } /* At least one valid signature found. */ /* Make sure that some fields in the assertion matches the same fields in the message. */ $asrtInResponseTo = $assertion->getInResponseTo(); $msgInResponseTo = $response->getInResponseTo(); if ($asrtInResponseTo !== NULL && $msgInResponseTo !== NULL) { if ($asrtInResponseTo !== $msgInResponseTo) { throw new SimpleSAML_Error_Exception('InResponseTo in assertion did not match InResponseTo in message.'); } } $asrtDestination = $assertion->getDestination(); $msgDestination = $response->getDestination(); if ($asrtDestination !== NULL && $msgDestination !== NULL) { if ($asrtDestination !== $msgDestination) { throw new SimpleSAML_Error_Exception('Destination in assertion did not match Destination in message.'); } } /* Check various properties of the assertion. */ $notBefore = $assertion->getNotBefore(); if ($notBefore > time() + 60) { throw new SimpleSAML_Error_Exception('Received an assertion that is valid in the future. Check clock synchronization on IdP and SP.'); } $notOnOrAfter = $assertion->getNotOnOrAfter(); if ($notOnOrAfter <= time() - 60) { throw new SimpleSAML_Error_Exception('Received an assertion that has expired. Check clock synchronization on IdP and SP.'); } $sessionNotOnOrAfter = $assertion->getSessionNotOnOrAfter(); if ($sessionNotOnOrAfter !== NULL && $sessionNotOnOrAfter <= time() - 60) { throw new SimpleSAML_Error_Exception('Received an assertion with a session that has expired. Check clock synchronization on IdP and SP.'); } $destination = $assertion->getDestination(); $currentURL = SimpleSAML_Utilities::selfURLNoQuery(); if ($destination !== $currentURL) { throw new Exception('Recipient in assertion doesn\'t match the current URL. Recipient is "' . $destination . '", current URL is "' . $currentURL . '".'); } $validAudiences = $assertion->getValidAudiences(); if ($validAudiences !== NULL) { $spEntityId = $spMetadata->getString('entityid'); if (!in_array($spEntityId, $validAudiences, TRUE)) { $candidates = '[' . implode('], [', $validAudiences) . ']'; throw new SimpleSAML_Error_Exception('This SP [' . $spEntityId . '] is not a valid audience for the assertion. Candidates were: ' . $candidates); } } /* As far as we can tell, the assertion is valid. */ /* Maybe we need to base64 decode the attributes in the assertion? */ if ($idpMetadata->getBoolean('base64attributes', FALSE)) { $attributes = $assertion->getAttributes(); $newAttributes = array(); foreach ($attributes as $name => $values) { $newAttributes[$name] = array(); foreach ($values as $value) { foreach (explode('_', $value) as $v) { $newAttributes[$name][] = base64_decode($v); } } } $assertion->setAttributes($newAttributes); } /* Decrypt the NameID element if it is encrypted. */ if ($assertion->isNameIdEncrypted()) { try { $key = self::getDecryptionKey($idpMetadata, $spMetadata); } catch (Exception $e) { throw new SimpleSAML_Error_Exception('Error decrypting NameID: ' . $e->getMessage()); } $assertion->decryptNameId($key); } return $assertion; }