Viewing file: saml2-logout.php (3.83 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
/** * Logout endpoint handler for SAML SP authentication client. * * This endpoint handles both logout requests and logout responses. */
if (!array_key_exists('PATH_INFO', $_SERVER)) { throw new SimpleSAML_Error_BadRequest('Missing authentication source id in logout URL'); }
$sourceId = substr($_SERVER['PATH_INFO'], 1);
$source = SimpleSAML_Auth_Source::getById($sourceId); if ($source === NULL) { throw new Exception('Could not find authentication source with id ' . $sourceId); } if (!($source instanceof sspmod_saml_Auth_Source_SP)) { throw new SimpleSAML_Error_Exception('Source type changed?'); }
$binding = SAML2_Binding::getCurrentBinding(); $message = $binding->receive();
$idpEntityId = $message->getIssuer(); 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.'); }
$spEntityId = $source->getEntityId();
$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); $idpMetadata = $source->getIdPMetadata($idpEntityId); $spMetadata = $source->getMetadata();
sspmod_saml_Message::validateMessage($idpMetadata, $spMetadata, $message);
$destination = $message->getDestination(); if ($destination !== NULL && $destination !== SimpleSAML_Utilities::selfURLNoQuery()) { throw new SimpleSAML_Error_Exception('Destination in logout message is wrong.'); }
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.'); }
if (!$message->isSuccess()) { SimpleSAML_Logger::warning('Unsuccessful logout. Status was: ' . sspmod_saml_Message::getResponseError($message)); }
$state = SimpleSAML_Auth_State::loadState($relayState, 'saml:slosent'); $state['saml:sp:LogoutStatus'] = $message->getStatus(); SimpleSAML_Auth_Source::completeLogout($state);
} elseif ($message instanceof SAML2_LogoutRequest) {
SimpleSAML_Logger::debug('module/saml2/sp/logout: Request from ' . $idpEntityId); SimpleSAML_Logger::stats('saml20-idp-SLO idpinit ' . $spEntityId . ' ' . $idpEntityId);
if ($message->isNameIdEncrypted()) { try { $keys = sspmod_saml_Message::getDecryptionKeys($idpMetadata, $spMetadata); } catch (Exception $e) { throw new SimpleSAML_Error_Exception('Error decrypting NameID: ' . $e->getMessage()); }
$blacklist = sspmod_saml_Message::getBlacklistedAlgorithms($idpMetadata, $spMetadata);
$lastException = NULL; foreach ($keys as $i => $key) { try { $message->decryptNameId($key, $blacklist); SimpleSAML_Logger::debug('Decryption with key #' . $i . ' succeeded.'); $lastException = NULL; break; } catch (Exception $e) { SimpleSAML_Logger::debug('Decryption with key #' . $i . ' failed with exception: ' . $e->getMessage()); $lastException = $e; } } if ($lastException !== NULL) { throw $lastException; } }
$nameId = $message->getNameId(); $sessionIndexes = $message->getSessionIndexes();
$numLoggedOut = sspmod_saml_SP_LogoutStore::logoutSessions($sourceId, $nameId, $sessionIndexes); if ($numLoggedOut === FALSE) { /* This type of logout was unsupported. Use the old method. */ $source->handleLogout($idpEntityId); $numLoggedOut = count($sessionIndexes); }
/* Create an send response. */ $lr = sspmod_saml_Message::buildLogoutResponse($spMetadata, $idpMetadata); $lr->setRelayState($message->getRelayState()); $lr->setInResponseTo($message->getId());
if ($numLoggedOut < count($sessionIndexes)) { SimpleSAML_Logger::warning('Logged out of ' . $numLoggedOut . ' of ' . count($sessionIndexes) . ' sessions.'); }
$binding->send($lr); } else { throw new SimpleSAML_Error_BadRequest('Unknown message received on logout endpoint: ' . get_class($message)); }
|