/** * Helper function for handling exception/errors. * * This function will send an error response to the SP which contacted this IdP. * * @param Exception $exception The exception. */ function handleError(Exception $exception) { global $requestcache, $config, $metadata, $idpentityid; assert('is_array($requestcache)'); assert('array_key_exists("Issuer", $requestcache)'); $issuer = $requestcache['Issuer']; if (array_key_exists('RequestID', $requestcache)) { $requestID = $requestcache['RequestID']; } else { $requestID = NULL; } if (array_key_exists('RelayState', $requestcache)) { $relayState = $requestcache['RelayState']; } else { $relayState = NULL; } $error = sspmod_saml2_Error::fromException($exception); SimpleSAML_Logger::warning('Returning error to sp: ' . var_export($issuer, TRUE)); $error->logWarning(); try { $idpMetadata = $metadata->getMetaDataConfig($idpentityid, 'saml20-idp-hosted'); $spMetadata = $metadata->getMetaDataConfig($issuer, 'saml20-sp-remote'); if (array_key_exists('ConsumerURL', $requestcache)) { $consumerURL = $requestcache['ConsumerURL']; } else { $urlArray = $spMetadata->getArrayizeString('AssertionConsumerService'); $consumerURL = $urlArray[0]; } $ar = sspmod_saml2_Message::buildResponse($idpMetadata, $spMetadata, $consumerURL); $ar->setInResponseTo($requestID); $ar->setRelayState($relayState); $ar->setStatus(array('Code' => $error->getStatus(), 'SubCode' => $error->getSubStatus(), 'Message' => $error->getStatusMessage())); $binding = new SAML2_HTTPPost(); $binding->setDestination(sspmod_SAML2_Message::getDebugDestination()); $binding->send($ar); } catch (Exception $e) { SimpleSAML_Utilities::fatalError($session->getTrackID(), 'GENERATEAUTHNRESPONSE', $e); } }
$spEntityId = $source->getEntityId(); $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); $idpMetadata = $metadata->getMetaDataConfig($idpEntityId, 'saml20-idp-remote'); $spMetadata = $source->getMetadata(); sspmod_saml2_Message::validateMessage($idpMetadata, $spMetadata, $message); 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_saml2_Message::getResponseError($message)); } $state = SimpleSAML_Auth_State::loadState($relayState, sspmod_saml2_Auth_Source_SP::STAGE_LOGOUTSENT); 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); /* Notify source of logout, so that it may call logout callbacks. */ $source->onLogout($idpEntityId); /* Create an send response. */ $lr = sspmod_saml2_Message::buildLogoutResponse($spMetadata, $idpMetadata); $lr->setRelayState($message->getRelayState()); $lr->setInResponseTo($message->getId()); $binding = new SAML2_HTTPRedirect(); $binding->setDestination(sspmod_SAML2_Message::getDebugDestination()); $binding->send($lr); } else { throw new SimpleSAML_Error_BadRequest('Unknown message received on logout endpoint: ' . get_class($message)); }
/** * Start a SAML 2 logout operation. * * @param array $state The logout state. */ public function startSLO2(&$state) { assert('is_array($state)'); assert('array_key_exists("saml:logout:IdP", $state)'); assert('array_key_exists("saml:logout:NameID", $state)'); assert('array_key_exists("saml:logout:SessionIndex", $state)'); $id = SimpleSAML_Auth_State::saveState($state, 'saml:slosent'); $idp = $state['saml:logout:IdP']; $nameId = $state['saml:logout:NameID']; $sessionIndex = $state['saml:logout:SessionIndex']; $idpMetadata = $this->getIdPMetadata($idp); $endpoint = $idpMetadata->getString('SingleLogoutService', FALSE); if ($endpoint === FALSE) { SimpleSAML_Logger::info('No logout endpoint for IdP ' . var_export($idp, TRUE) . '.'); return; } $lr = sspmod_saml2_Message::buildLogoutRequest($this->metadata, $idpMetadata); $lr->setNameId($nameId); $lr->setSessionIndex($sessionIndex); $lr->setRelayState($id); $b = new SAML2_HTTPRedirect(); $b->setDestination(sspmod_SAML2_Message::getDebugDestination()); $b->send($lr); assert('FALSE'); }
* Check if the Single Logout procedure is initated by an SP (alternatively IdP initiated SLO) */ if (array_key_exists('Issuer', $logoutInfo)) { $spMetadata = $metadata->getMetaDataConfig($logoutInfo['Issuer'], 'saml20-sp-remote'); // Find the relaystate if cached. $relayState = isset($logoutInfo['RelayState']) ? $logoutInfo['RelayState'] : null; /* Create a Logout Response. */ $rg = sspmod_saml2_Message::buildLogoutResponse($idpMetadata, $spMetadata); $rg->setInResponseTo($logoutInfo['RequestID']); $rg->setRelayState($relayState); $httpredirect = new SAML2_HTTPRedirect(); /* * If the user is not logged into any other SPs, send the LogoutResponse immediately */ if (count($sparray) + count($sparrayNoLogout) === 0) { $httpredirect->setDestination(sspmod_SAML2_Message::getDebugDestination()); $httpredirect->send($rg); } else { $logoutresponse = $httpredirect->getRedirectURL($rg); } } elseif (array_key_exists('RelayState', $logoutInfo)) { SimpleSAML_Utilities::redirect($logoutInfo['RelayState']); exit; } else { echo 'You are logged out'; exit; } } catch (Exception $exception) { SimpleSAML_Utilities::fatalError($session->getTrackID(), 'GENERATELOGOUTRESPONSE', $exception); } $spmeta = $metadata->getMetaData($requester, 'saml20-sp-remote');
/** * Handle logout operation. * * @param array $state The logout state. */ public function logout(&$state) { assert('is_array($state)'); assert('array_key_exists(self::LOGOUT_IDP, $state)'); assert('array_key_exists(self::LOGOUT_NAMEID, $state)'); assert('array_key_exists(self::LOGOUT_SESSIONINDEX, $state)'); $id = SimpleSAML_Auth_State::saveState($state, self::STAGE_LOGOUTSENT); $idp = $state[self::LOGOUT_IDP]; $nameId = $state[self::LOGOUT_NAMEID]; $sessionIndex = $state[self::LOGOUT_SESSIONINDEX]; if (array_key_exists('value', $nameId)) { /* * This session was saved by an old version of simpleSAMLphp. * Convert to the new NameId format. * * TODO: Remove this conversion once every session should use the new format. */ $nameId['Value'] = $nameId['value']; unset($nameId['value']); } $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); $idpMetadata = $metadata->getMetaDataConfig($idp, 'saml20-idp-remote'); $lr = sspmod_saml2_Message::buildLogoutRequest($this->metadata, $idpMetadata); $lr->setNameId($nameId); $lr->setSessionIndex($sessionIndex); $lr->setRelayState($id); $b = new SAML2_HTTPRedirect(); $b->setDestination(sspmod_SAML2_Message::getDebugDestination()); $b->send($lr); assert('FALSE'); }