Exemple #1
0
 /**
  * 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);
 }
Exemple #3
0
 /**
  * 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));
     }
 }