/** * Test binding guessing functionality with unsupported HTTP method. */ public function testBindingGuesserWRONG() { $_SERVER['REQUEST_METHOD'] = 'PUT'; $_SERVER['CONTENT_TYPE'] = 'text/xml'; $this->setExpectedException('Exception', 'Unable to find the current binding.'); $bind = Binding::getCurrentBinding(); }
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); }
<?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.'); }
/** * 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)); } }