function handleResponse() { try { $binding = SAML2_Binding::getCurrentBinding(); $response = $binding->receive(); } catch (Exception $e) { return; } SimpleSAML_Logger::debug('attributequery - received message.'); if (!$response instanceof SAML2_Response) { throw new SimpleSAML_Error_Exception('Unexpected message received to attribute query example.'); } $idpEntityId = $response->getIssuer(); if ($idpEntityId === NULL) { throw new SimpleSAML_Error_Exception('Missing issuer in response.'); } $idpMetadata = $GLOBALS['metadata']->getMetaDataConfig($idpEntityId, 'saml20-idp-remote'); $spMetadata = $GLOBALS['metadata']->getMetaDataConfig($GLOBALS['spEntityId'], 'saml20-sp-hosted'); $assertion = sspmod_saml2_Message::processResponse($spMetadata, $idpMetadata, $response); $dataId = $response->getRelayState(); if ($dataId === NULL) { throw new SimpleSAML_Error_Exception('RelayState was lost during request.'); } $data = $GLOBALS['session']->getData('attributequeryexample:data', $dataId); $data['attributes'] = $assertion->getAttributes(); $GLOBALS['session']->setData('attributequeryexample:data', $dataId, $data, 3600); SimpleSAML_Utilities::redirect(SimpleSAML_Utilities::selfURLNoQuery(), array('dataId' => $dataId)); }
protected function createLogoutResponse($testrun, $logoutRequest, $logoutRelayState) { $this->log($testrun, 'Creating response with relaystate [' . $logoutRelayState . ']'); $idpMetadata = SimpleSAML_Configuration::loadFromArray($this->idpmetadata); $spMetadata = SimpleSAML_Configuration::loadFromArray($this->metadata); // Get SingleLogoutService URL $consumerURLf = $spMetadata->getDefaultEndpoint('SingleLogoutService', array('urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect')); $consumerURL = $consumerURLf['Location']; /* Create an send response. */ $response = sspmod_saml2_Message::buildLogoutResponse($idpMetadata, $spMetadata); $response->setRelayState($logoutRequest->getRelayState()); $response->setInResponseTo($logoutRequest->getId()); $keyArray = SimpleSAML_Utilities::loadPrivateKey($idpMetadata, TRUE); $certArray = SimpleSAML_Utilities::loadPublicKey($idpMetadata, FALSE); $privateKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'private')); $privateKey->loadKey($keyArray['PEM'], FALSE); $response->setSignatureKey($privateKey); if ($certArray === NULL) { throw new Exception('No certificates found. [1]'); } if (!array_key_exists('PEM', $certArray)) { throw new Exception('No certificates found. [2]'); } $response->setCertificates(array($certArray['PEM'])); #$this->tweakResponse($testrun, $response); $msgStr = $response->toUnsignedXML(); #$this->tweakResponseDOM($testrun, $msgStr); $msgStr = $msgStr->ownerDocument->saveXML($msgStr); # echo '<pre>'; echo(htmlspecialchars($msgStr)); exit; # $msgStr = base64_encode($msgStr); # $msgStr = htmlspecialchars($msgStr); return array('url' => $consumerURL, 'Response' => $msgStr, 'ResponseObj' => $response, 'RelayState' => $logoutRelayState); }
/** * 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)); }
if ($source === NULL) { throw new Exception('Could not find authentication source with id ' . $sourceId); } $idp = $response->getIssuer(); if ($idp === NULL) { throw new Exception('Missing <saml:Issuer> in message delivered to AssertionConsumerService.'); } $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); $idpMetadata = $metadata->getMetaDataConfig($idp, 'saml20-idp-remote'); $spMetadata = $source->getMetadata(); /* Check if the IdP is allowed to authenticate users for this authentication source. */ if (!$source->isIdPValid($idp)) { throw new Exception('Invalid IdP responded for authentication source with id ' . $sourceId . '. The IdP was ' . var_export($idp, TRUE)); } try { $assertion = sspmod_saml2_Message::processResponse($spMetadata, $idpMetadata, $response); } catch (sspmod_saml2_Error $e) { /* The status of the response wasn't "success". */ $e = $e->toException(); SimpleSAML_Auth_State::throwException($state, $e); } $nameId = $assertion->getNameId(); $sessionIndex = $assertion->getSessionIndex(); /* We need to save the NameID and SessionIndex for logout. */ $logoutState = array(sspmod_saml2_Auth_Source_SP::LOGOUT_IDP => $idp, sspmod_saml2_Auth_Source_SP::LOGOUT_NAMEID => $nameId, sspmod_saml2_Auth_Source_SP::LOGOUT_SESSIONINDEX => $sessionIndex); $state['LogoutState'] = $logoutState; $spMetadataArray = $spMetadata->toArray(); $idpMetadataArray = $idpMetadata->toArray(); $pc = new SimpleSAML_Auth_ProcessingChain($idpMetadataArray, $spMetadataArray, 'sp'); $authProcState = array('saml2:sp:IdP' => $idp, 'saml2:sp:State' => $state, 'ReturnCall' => array('sspmod_saml2_Auth_Source_SP', 'onProcessingCompleted'), 'Attributes' => $assertion->getAttributes(), 'Destination' => $spMetadataArray, 'Source' => $idpMetadataArray); $pc->processState($authProcState);
if (count($values) === 0) { /* Return all attributes. */ $returnAttributes[$name] = $attributes[$name]; continue; } /* Filter which attribute values we should return. */ $returnAttributes[$name] = array_intersect($values, $attributes[$name]); } } /* $returnAttributes contains the attributes we should return. Send them. */ $assertion = new SAML2_Assertion(); $assertion->setDestination($endpoint); $assertion->setIssuer($idpEntityId); $assertion->setNameId($query->getNameId()); $assertion->setNotBefore(time()); $assertion->setNotOnOrAfter(time() + 5 * 60); $assertion->setInResponseTo($query->getId()); $assertion->setValidAudiences(array($spEntityId)); $assertion->setAttributes($returnAttributes); $assertion->setAttributeNameFormat($attributeNameFormat); sspmod_saml2_Message::addSign($idpMetadata, $spMetadata, $assertion); $response = new SAML2_Response(); $response->setRelayState($query->getRelayState()); $response->setDestination($endpoint); $response->setIssuer($idpEntityId); $response->setInResponseTo($query->getId()); $response->setAssertions(array($assertion)); sspmod_saml2_Message::addSign($idpMetadata, $spMetadata, $response); $binding = new SAML2_HTTPPost(); $binding->setDestination(sspmod_saml2_Message::getDebugDestination()); $binding->send($response);
/** * 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'); }
$logouttype = $idpMetadata->getString('logouttype', 'traditional'); if ($logouttype !== 'iframe') { SimpleSAML_Utilities::fatalError($session->getTrackID(), 'NOACCESS', new Exception('This IdP is configured to use logout type [' . $logouttype . '], but this endpoint is only available for IdP using logout type [iframe]')); } if (!isset($_REQUEST['SAMLResponse'])) { SimpleSAML_Utilities::fatalError($session->getTrackID(), 'SLOSERVICEPARAMS', new Exception('No valid SAMLResponse found? Probably some error in remote partys metadata that sends something to this endpoint that is not SAML LogoutResponses')); } $binding = SAML2_Binding::getCurrentBinding(); $logoutResponse = $binding->receive(); if (!$logoutResponse instanceof SAML2_LogoutResponse) { SimpleSAML_Utilities::fatalError($session->getTrackID(), 'SLOSERVICEPARAMS', new Exception('Message received on response endpoint wasn\'t a response. Was: ' . get_class($logoutResponse))); } $spEntityId = $logoutResponse->getIssuer(); if ($spEntityId === NULL) { SimpleSAML_Utilities::fatalError($session->getTrackID(), 'SLOSERVICEPARAMS', new Exception('Missing issuer on logout response.')); } $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'saml20-sp-remote'); sspmod_saml2_Message::validateMessage($spMetadata, $idpMetadata, $logoutResponse); $sphash = sha1($spEntityId); setcookie('spstate-' . $sphash, '1'); // Duration: 2 hours SimpleSAML_Logger::info('SAML2.0 - IdP.SingleLogoutServiceiFrameResponse: Logging out completed'); echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title>Logout OK</title> </head> <body>OK</body> </html>';
SimpleSAML_Utilities::redirect($extDiscoveryStorage, array('entityID' => $spentityid, 'return' => SimpleSAML_Utilities::addURLparameter($discourl, array('return' => SimpleSAML_Utilities::selfURL(), 'remember' => 'true', 'entityID' => $spentityid, 'returnIDParam' => 'idpentityid')), 'returnIDParam' => 'idpentityid', 'isPassive' => 'true')); } $discoparameters = array('entityID' => $spentityid, 'return' => SimpleSAML_Utilities::selfURL(), 'returnIDParam' => 'idpentityid'); $discoparameters['isPassive'] = $isPassive; if (sizeof($reachableIDPs) > 0) { $discoparameters['IDPList'] = $reachableIDPs; } SimpleSAML_Utilities::redirect($discourl, $discoparameters); } /* * Create and send authentication request to the IdP. */ try { $spMetadata = $metadata->getMetaDataConfig($spentityid, 'saml20-sp-hosted'); $idpMetadata = $metadata->getMetaDataConfig($idpentityid, 'saml20-idp-remote'); $ar = sspmod_saml2_Message::buildAuthnRequest($spMetadata, $idpMetadata); $assertionConsumerServiceURL = $metadata->getGenerated('AssertionConsumerService', 'saml20-sp-hosted'); $ar->setAssertionConsumerServiceURL($assertionConsumerServiceURL); $ar->setProtocolBinding(SAML2_Const::BINDING_HTTP_POST); $ar->setRelayState($_REQUEST['RelayState']); if ($isPassive) { $ar->setIsPassive(TRUE); } if ($forceAuthn) { $ar->setForceAuthn(TRUE); } if (array_key_exists('IDPList', $spmetadata)) { $IDPList = array_unique(array_merge($IDPList, $spmetadata['IDPList'])); } if (isset($_GET['IDPList']) && !empty($_GET['IDPList'])) { $providers = $_GET['IDPList'];
/** * 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'); }
/* * Generate a list of all service providers, and create a LogoutRequest message for all these SPs. */ $listofsps = $session->get_sp_list(); $sparray = array(); $sparrayNoLogout = array(); foreach ($listofsps as $spentityid) { // ($issuer, $receiver, $nameid, $nameidformat, $sessionindex, $mode) { $nameId = $session->getSessionNameId('saml20-sp-remote', $spentityid); if ($nameId === NULL) { $nameId = $session->getNameID(); } $spMetadata = $metadata->getMetaDataConfig($spentityid, 'saml20-sp-remote'); $name = $spMetadata->getValue('name', $spentityid); try { $lr = sspmod_saml2_Message::buildLogoutRequest($idpMetadata, $spMetadata); $lr->setSessionIndex($session->getSessionIndex()); $lr->setNameId($nameId); $httpredirect = new SAML2_HTTPRedirect(); $url = $httpredirect->getRedirectURL($lr); $sparray[$spentityid] = array('url' => $url, 'name' => $name); } catch (Exception $e) { $sparrayNoLogout[$spentityid] = array('name' => $name); } } SimpleSAML_Logger::debug('SAML2.0 - SP Counter. other SPs with SLO support (' . count($sparray) . ') without SLO support (' . count($sparrayNoLogout) . ')'); #print_r($sparray); /* * If the user is not logged into any other SPs. */ if (count($sparray) + count($sparrayNoLogout) === 0) {