Skip to content
Snippets Groups Projects
Commit 6b91de0e authored by Olav Morken's avatar Olav Morken
Browse files

saml2: Use SAML library for handling logout messages from IdP.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@1609 44740490-163a-0410-bde0-09ae8108e29a
parent 546083c5
No related branches found
No related tags found
No related merge requests found
...@@ -181,6 +181,34 @@ class sspmod_saml2_Message { ...@@ -181,6 +181,34 @@ class sspmod_saml2_Message {
} }
/**
* Check signature on a SAML2 message if enabled.
*
* @param SimpleSAML_Configuration $srcMetadata The metadata of the sender.
* @param SimpleSAML_Configuration $dstMetadata The metadata of the recipient.
* @param SAML2_Message $message The message we should check the signature on.
*/
public static function validateMessage(
SimpleSAML_Configuration $srcMetadata,
SimpleSAML_Configuration $dstMetadata,
SAML2_Message $message
) {
$enabled = $srcMetadata->getBoolean('redirect.validate', NULL);
if ($enabled === NULL) {
$enabled = $dstMetadata->getBoolean('redirect.validate', FALSE);
}
if (!$enabled) {
return;
}
if (!self::checkSign($srcMetadata, $message)) {
throw new SimpleSAML_Error_Exception('Validation of received messages enabled, but no signature found on message.');
}
}
/** /**
* Decrypt an assertion. * Decrypt an assertion.
* *
...@@ -293,6 +321,30 @@ class sspmod_saml2_Message { ...@@ -293,6 +321,30 @@ class sspmod_saml2_Message {
} }
/**
* Build a logout response based on information in the metadata.
*
* @param SimpleSAML_Configuration $srcMetadata The metadata of the sender.
* @param SimpleSAML_Configuration $dstpMetadata The metadata of the recipient.
*/
public static function buildLogoutResponse(SimpleSAML_Configuration $srcMetadata, SimpleSAML_Configuration $dstMetadata) {
$lr = new SAML2_LogoutResponse();
$lr->setIssuer($srcMetadata->getString('entityid'));
$dst = $dstMetadata->getString('SingleLogoutServiceResponse', NULL);
if ($dst === NULL) {
$dst = $dstMetadata->getString('SingleLogoutService');
}
$lr->setDestination($dst);
self::addSign($srcMetadata, $dstMetadata, $lr);
return $lr;
}
/** /**
* Process a response message. * Process a response message.
* *
......
...@@ -17,57 +17,54 @@ if ($source === NULL) { ...@@ -17,57 +17,54 @@ if ($source === NULL) {
throw new Exception('Could not find authentication source with id ' . $sourceId); throw new Exception('Could not find authentication source with id ' . $sourceId);
} }
$binding = SAML2_Binding::getCurrentBinding();
$message = $binding->receive();
$config = SimpleSAML_Configuration::getInstance(); $idpEntityId = $message->getIssuer();
$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); if ($idpEntityId === NULL) {
/* Without an issuer we have no way to respond to the message. */
throw new SimpleSAML_Error_BadRequest('Received message on logout endpoint without issuer.');
}
if (array_key_exists('SAMLResponse', $_GET)) { $spEntityId = $source->getEntityId();
$binding = new SimpleSAML_Bindings_SAML20_HTTPRedirect($config, $metadata); $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
$response = $binding->decodeLogoutResponse($_GET); $idpMetadata = $metadata->getMetaDataConfig($idpEntityId, 'saml20-idp-remote');
$spMetadata = $metadata->getMetaDataConfig($spEntityId, 'saml20-sp-hosted');
if ($binding->validateQuery($response->getIssuer(), 'SP', 'SAMLResponse')) { sspmod_saml2_Message::validateMessage($idpMetadata, $spMetadata, $message);
SimpleSAML_Logger::debug('module/saml2/sp/logout: Valid signature found on response');
}
if (!array_key_exists('RelayState', $_REQUEST)) { if ($message instanceof SAML2_LogoutResponse) {
$relayState = $message->getRelayState();
if ($relayState === NULL) {
/* Somehow, our RelayState has been lost. */
throw new SimpleSAML_Error_BadRequest('Missing RelayState in logout response.'); throw new SimpleSAML_Error_BadRequest('Missing RelayState in logout response.');
} }
$stateId = $_REQUEST['RelayState']; if (!$message->isSuccess()) {
$state = SimpleSAML_Auth_State::loadState($_REQUEST['RelayState'], sspmod_saml2_Auth_Source_SP::STAGE_LOGOUTSENT); SimpleSAML_Logger::warning('Unsuccessful logout. Status was: ' . sspmod_saml2_Message::getResponseError($message));
SimpleSAML_Auth_Source::completeLogout($state);
} elseif (array_key_exists('SAMLRequest', $_GET)) {
$binding = new SimpleSAML_Bindings_SAML20_HTTPRedirect($config, $metadata);
$request = $binding->decodeLogoutRequest($_GET);
$requestId = $request->getRequestID();
$idpEntityId = $request->getIssuer();
$relayState = $request->getRelayState();
if ($binding->validateQuery($idpEntityId, 'SP')) {
SimpleSAML_Logger::debug('module/saml2/sp/logout: Valid signature found on request');
} }
$state = SimpleSAML_Auth_State::loadState($relayState, sspmod_saml2_Auth_Source_SP::STAGE_LOGOUTSENT);
SimpleSAML_Auth_Source::completeLogout($state);
$spEntityId = $source->getEntityId(); } elseif ($message instanceof SAML2_LogoutRequest) {
SimpleSAML_Logger::debug('module/saml2/sp/logout: Request from ' . $idpEntityId . ' with request id ' . $requestId); SimpleSAML_Logger::debug('module/saml2/sp/logout: Request from ' . $idpEntityId);
SimpleSAML_Logger::stats('saml20-idp-SLO idpinit ' . $spEntityId . ' ' . $idpEntityId); SimpleSAML_Logger::stats('saml20-idp-SLO idpinit ' . $spEntityId . ' ' . $idpEntityId);
/* Notify source of logout, so that it may call logout callbacks. */ /* Notify source of logout, so that it may call logout callbacks. */
$source->onLogout($idpEntityId); $source->onLogout($idpEntityId);
/* Create an send response. */ /* Create an send response. */
$lr = new SimpleSAML_XML_SAML20_LogoutResponse($config, $metadata); $lr = sspmod_saml2_Message::buildLogoutResponse($spMetadata, $idpMetadata);
$responseXML = $lr->generate($spEntityId, $idpEntityId, $requestId, 'SP'); $lr->setRelayState($message->getRelayState());
$binding->sendMessage($responseXML, $spEntityId, $idpEntityId, $relayState, 'SingleLogoutServiceResponse', 'SAMLResponse'); $lr->setInResponseTo($message->getId());
$binding = new SAML2_HTTPRedirect();
$binding->setDestination(sspmod_SAML2_Message::getDebugDestination());
$binding->send($lr);
} else { } else {
throw new SimpleSAML_Error_BadRequest('Missing request or response to logout endpoint'); throw new SimpleSAML_Error_BadRequest('Unknown message received on logout endpoint: ' . get_class($message));
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment