/** * test destination getter and setter. */ public function testGetSetDestination() { $bind = Binding::getBinding(Constants::BINDING_HTTP_POST); $dest = $bind->getDestination(); $this->assertNull($dest); $bind->setDestination('http://example.org/example'); $dest = $bind->getDestination(); $this->assertEquals($dest, 'http://example.org/example'); }
public static function handleLoginRequest(IPerson $Person) { try { $binding = Binding::getCurrentBinding(); } catch (Exception $e) { return static::throwUnauthorizedError('Cannot obtain SAML2 binding'); } $request = $binding->receive(); // build response $response = new Response(); $response->setInResponseTo($request->getId()); $response->setRelayState($request->getRelayState()); $response->setDestination($request->getAssertionConsumerServiceURL()); // build assertion $assertion = new Assertion(); $assertion->setIssuer(static::$issuer); $assertion->setSessionIndex(ContainerSingleton::getInstance()->generateId()); $assertion->setNotBefore(time() - 30); $assertion->setNotOnOrAfter(time() + 300); $assertion->setAuthnContext(SAML2_Constants::AC_PASSWORD); // build subject confirmation $sc = new SubjectConfirmation(); $sc->Method = SAML2_Constants::CM_BEARER; $sc->SubjectConfirmationData = new SubjectConfirmationData(); $sc->SubjectConfirmationData->NotOnOrAfter = $assertion->getNotOnOrAfter(); $sc->SubjectConfirmationData->Recipient = $request->getAssertionConsumerServiceURL(); $sc->SubjectConfirmationData->InResponseTo = $request->getId(); $assertion->setSubjectConfirmation([$sc]); // set NameID $assertion->setNameId(['Format' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', 'Value' => $Person->Username . '@' . static::$issuer]); // set additional attributes $assertion->setAttributes(['User.Email' => [$Person->Email], 'User.Username' => [$Person->Username]]); // attach assertion to response $response->setAssertions([$assertion]); // create signature $privateKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, ['type' => 'private']); $privateKey->loadKey(static::$privateKey); $response->setSignatureKey($privateKey); $response->setCertificates([static::$certificate]); // prepare response $responseXML = $response->toSignedXML(); $responseString = $responseXML->ownerDocument->saveXML($responseXML); // dump response and quit # header('Content-Type: text/xml'); # die($responseString); // send response $responseBinding = new HTTPPost(); $responseBinding->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->getEndpointPrioritizedByBinding('SingleLogoutService', array(\SAML2\Constants::BINDING_HTTP_REDIRECT, \SAML2\Constants::BINDING_HTTP_POST), FALSE); if ($endpoint === FALSE) { SimpleSAML\Logger::info('No logout endpoint for IdP ' . var_export($idp, TRUE) . '.'); return; } $lr = sspmod_saml_Message::buildLogoutRequest($this->metadata, $idpMetadata); $lr->setNameId($nameId); $lr->setSessionIndex($sessionIndex); $lr->setRelayState($id); $lr->setDestination($endpoint['Location']); $encryptNameId = $idpMetadata->getBoolean('nameid.encryption', NULL); if ($encryptNameId === NULL) { $encryptNameId = $this->metadata->getBoolean('nameid.encryption', FALSE); } if ($encryptNameId) { $lr->encryptNameId(sspmod_saml_Message::getEncryptionKey($idpMetadata)); } $b = \SAML2\Binding::getBinding($endpoint['Binding']); $b->send($lr); assert('FALSE'); }
<?php /** * Assertion consumer service handler for SAML 2.0 SP authentication client. */ if (!array_key_exists('PATH_INFO', $_SERVER)) { throw new SimpleSAML_Error_BadRequest('Missing authentication source ID in assertion consumer service URL'); } $sourceId = substr($_SERVER['PATH_INFO'], 1); $source = SimpleSAML_Auth_Source::getById($sourceId, 'sspmod_saml_Auth_Source_SP'); $spMetadata = $source->getMetadata(); try { $b = \SAML2\Binding::getCurrentBinding(); } catch (Exception $e) { // TODO: look for a specific exception // This is dirty. Instead of checking the message of the exception, \SAML2\Binding::getCurrentBinding() should throw // an specific exception when the binding is unknown, and we should capture that here if ($e->getMessage() === 'Unable to find the current binding.') { throw new SimpleSAML_Error_Error('ACSPARAMS', $e, 400); } else { throw $e; // do not ignore other exceptions! } } if ($b instanceof \SAML2\HTTPArtifact) { $b->setSPMetadata($spMetadata); } $response = $b->receive(); if (!$response instanceof \SAML2\Response) { throw new SimpleSAML_Error_BadRequest('Invalid message received to AssertionConsumerService endpoint.'); }
} $associations = $idp->getAssociations(); if (!isset($associations[$assocId])) { throw new SimpleSAML_Error_BadRequest('Invalid association id.'); } $association = $associations[$assocId]; $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); $idpMetadata = $idp->getConfig(); $spMetadata = $metadata->getMetaDataConfig($association['saml:entityID'], 'saml20-sp-remote'); $lr = sspmod_saml_Message::buildLogoutRequest($idpMetadata, $spMetadata); $lr->setSessionIndex($association['saml:SessionIndex']); $lr->setNameId($association['saml:NameID']); $assertionLifetime = $spMetadata->getInteger('assertion.lifetime', NULL); if ($assertionLifetime === NULL) { $assertionLifetime = $idpMetadata->getInteger('assertion.lifetime', 300); } $lr->setNotOnOrAfter(time() + $assertionLifetime); $encryptNameId = $spMetadata->getBoolean('nameid.encryption', NULL); if ($encryptNameId === NULL) { $encryptNameId = $idpMetadata->getBoolean('nameid.encryption', FALSE); } if ($encryptNameId) { $lr->encryptNameId(sspmod_saml_Message::getEncryptionKey($spMetadata)); } SimpleSAML_Stats::log('saml:idp:LogoutRequest:sent', array('spEntityID' => $association['saml:entityID'], 'idpEntityID' => $idpMetadata->getString('entityid'))); $bindings = array(\SAML2\Constants::BINDING_HTTP_POST); $dst = $spMetadata->getDefaultEndpoint('SingleLogoutService', $bindings); $binding = \SAML2\Binding::getBinding($dst['Binding']); $lr->setDestination($dst['Location']); $lr->setRelayState($relayState); $binding->send($lr);
/** * Receive a logout message. * * @param SimpleSAML_IdP $idp The IdP we are receiving it for. * @throws SimpleSAML_Error_BadRequest In case an error occurs while trying to receive the logout message. */ public static function receiveLogoutMessage(SimpleSAML_IdP $idp) { $binding = \SAML2\Binding::getCurrentBinding(); $message = $binding->receive(); $spEntityId = $message->getIssuer(); if ($spEntityId === 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.'); } $metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler(); $idpMetadata = $idp->getConfig(); $spMetadata = $metadata->getMetaDataConfig($spEntityId, 'saml20-sp-remote'); sspmod_saml_Message::validateMessage($spMetadata, $idpMetadata, $message); if ($message instanceof \SAML2\LogoutResponse) { SimpleSAML\Logger::info('Received SAML 2.0 LogoutResponse from: ' . var_export($spEntityId, true)); $statsData = array('spEntityID' => $spEntityId, 'idpEntityID' => $idpMetadata->getString('entityid')); if (!$message->isSuccess()) { $statsData['error'] = $message->getStatus(); } SimpleSAML_Stats::log('saml:idp:LogoutResponse:recv', $statsData); $relayState = $message->getRelayState(); if (!$message->isSuccess()) { $logoutError = sspmod_saml_Message::getResponseError($message); SimpleSAML\Logger::warning('Unsuccessful logout. Status was: ' . $logoutError); } else { $logoutError = null; } $assocId = 'saml:' . $spEntityId; $idp->handleLogoutResponse($assocId, $relayState, $logoutError); } elseif ($message instanceof \SAML2\LogoutRequest) { SimpleSAML\Logger::info('Received SAML 2.0 LogoutRequest from: ' . var_export($spEntityId, true)); SimpleSAML_Stats::log('saml:idp:LogoutRequest:recv', array('spEntityID' => $spEntityId, 'idpEntityID' => $idpMetadata->getString('entityid'))); $spStatsId = $spMetadata->getString('core:statistics-id', $spEntityId); SimpleSAML\Logger::stats('saml20-idp-SLO spinit ' . $spStatsId . ' ' . $idpMetadata->getString('entityid')); $state = array('Responder' => array('sspmod_saml_IdP_SAML2', 'sendLogoutResponse'), 'saml:SPEntityId' => $spEntityId, 'saml:RelayState' => $message->getRelayState(), 'saml:RequestId' => $message->getId()); $assocId = 'saml:' . $spEntityId; $idp->handleLogoutRequest($state, $assocId); } else { throw new SimpleSAML_Error_BadRequest('Unknown message received on logout endpoint: ' . get_class($message)); } }