/**
  * Filter the response.
  *
  * @param EngineBlock_Saml2_ResponseAnnotationDecorator     $response
  * @param array                                             $responseAttributes
  * @param EngineBlock_Saml2_AuthnRequestAnnotationDecorator $request
  * @param ServiceProvider                             $serviceProvider
  * @param IdentityProvider                            $identityProvider
  * @throws EngineBlock_Exception
  * @throws Exception
  */
 public function filter(EngineBlock_Saml2_ResponseAnnotationDecorator $response, array &$responseAttributes, EngineBlock_Saml2_AuthnRequestAnnotationDecorator $request, ServiceProvider $serviceProvider, IdentityProvider $identityProvider)
 {
     /** @var SAML2_AuthnRequest $request */
     // Note that IDs are only unique per SP... we hope...
     $responseNameId = $response->getAssertion()->getNameId();
     $sessionKey = $serviceProvider->entityId . '>' . $request->getId();
     if (isset($_SESSION[$sessionKey]['collabPersonId'])) {
         $collabPersonId = $_SESSION[$sessionKey]['collabPersonId'];
     } else {
         if ($response->getCollabPersonId()) {
             $collabPersonId = $response->getCollabPersonId();
         } else {
             if (isset($responseAttributes['urn:oid:1.3.6.1.4.1.1076.20.40.40.1'][0])) {
                 $collabPersonId = $responseAttributes['urn:oid:1.3.6.1.4.1.1076.20.40.40.1'][0];
             } else {
                 if (!empty($responseNameId['Value'])) {
                     $collabPersonId = $responseNameId['Value'];
                 } else {
                     $collabPersonId = null;
                 }
             }
         }
     }
     $commands = $this->_getCommands();
     /** @var EngineBlock_Corto_Filter_Command_Abstract $command */
     foreach ($commands as $command) {
         // Inject everything we have into the adapter
         $command->setProxyServer($this->_server);
         $command->setIdentityProvider($identityProvider);
         $command->setServiceProvider($serviceProvider);
         $command->setRequest($request);
         $command->setResponse($response);
         $command->setResponseAttributes($responseAttributes);
         $command->setCollabPersonId($collabPersonId);
         // Execute the command
         try {
             $command->execute();
         } catch (EngineBlock_Exception $e) {
             $e->idpEntityId = $identityProvider->entityId;
             $e->spEntityId = $serviceProvider->entityId;
             $e->userId = $collabPersonId;
             throw $e;
         }
         if (method_exists($command, 'getResponse')) {
             $response = $command->getResponse();
         }
         if (method_exists($command, 'getResponseAttributes')) {
             $responseAttributes = $command->getResponseAttributes();
         }
         if (method_exists($command, 'getCollabPersonId')) {
             $collabPersonId = $command->getCollabPersonId();
         }
         // Give the command a chance to stop filtering
         if (!$command->mustContinueFiltering()) {
             break;
         }
     }
     $_SESSION[$sessionKey]['collabPersonId'] = $collabPersonId;
 }
 public function testToString()
 {
     $request = new SAML2_AuthnRequest();
     $request->setId('TEST123');
     $request->setIssueInstant(0);
     $annotatedRequest = new EngineBlock_Saml2_AuthnRequestAnnotationDecorator($request);
     $annotatedRequest->setDebug();
     $this->assertEquals('{"sspMessage":"<?xml version=\\"1.0\\"?>\\n<samlp:AuthnRequest xmlns:samlp=\\"urn:oasis:names:tc:SAML:2.0:protocol\\" xmlns:saml=\\"urn:oasis:names:tc:SAML:2.0:assertion\\" ID=\\"TEST123\\" Version=\\"2.0\\" IssueInstant=\\"1970-01-01T00:00:00Z\\"\\/>\\n","voContext":null,"keyId":null,"explicitVoContext":true,"wasSigned":false,"debug":true,"unsolicited":false,"transparent":false,"deliverByBinding":null}', $annotatedRequest->__toString());
 }
 public static function cacheResponse(EngineBlock_Saml2_AuthnRequestAnnotationDecorator $receivedRequest, EngineBlock_Saml2_ResponseAnnotationDecorator $receivedResponse, $type)
 {
     if ($type !== self::RESPONSE_CACHE_TYPE_IN) {
         throw new EngineBlock_Exception('Unknown response type');
     }
     if (!isset($_SESSION['CachedResponses'])) {
         $_SESSION['CachedResponses'] = array();
     }
     $_SESSION['CachedResponses'][] = array('sp' => $receivedRequest->getIssuer(), 'idp' => $receivedResponse->getIssuer(), 'type' => $type, 'response' => $receivedResponse, 'vo' => $receivedRequest->getVoContext(), 'key' => $receivedRequest->getKeyId());
 }
 public static function createFromRequest(EngineBlock_Saml2_AuthnRequestAnnotationDecorator $originalRequest, IdentityProvider $idpMetadata, EngineBlock_Corto_ProxyServer $server)
 {
     $nameIdPolicy = array('AllowCreate' => 'true');
     /**
      * Name policy is not required, so it is only set if configured, SAML 2.0 spec
      * says only following values are allowed:
      *  - urn:oasis:names:tc:SAML:2.0:nameid-format:transient
      *  - urn:oasis:names:tc:SAML:2.0:nameid-format:persistent.
      *
      * Note: Some IDP's like those using ADFS2 do not understand those, for these cases the format can be 'configured as empty
      * or set to an older version.
      */
     if (!empty($idpMetadata->nameIdFormat)) {
         $nameIdPolicy['Format'] = $idpMetadata->nameIdFormat;
     }
     /** @var SAML2_AuthnRequest $originalRequest */
     $sspRequest = new SAML2_AuthnRequest();
     $sspRequest->setId($server->getNewId(\OpenConext\Component\EngineBlockFixtures\IdFrame::ID_USAGE_SAML2_REQUEST));
     $sspRequest->setIssueInstant(time());
     $sspRequest->setDestination($idpMetadata->singleSignOnServices[0]->location);
     $sspRequest->setForceAuthn($originalRequest->getForceAuthn());
     $sspRequest->setIsPassive($originalRequest->getIsPassive());
     $sspRequest->setAssertionConsumerServiceURL($server->getUrl('assertionConsumerService'));
     $sspRequest->setProtocolBinding(SAML2_Const::BINDING_HTTP_POST);
     $sspRequest->setIssuer($server->getUrl('spMetadataService'));
     $sspRequest->setNameIdPolicy($nameIdPolicy);
     if (empty($idpMetadata->disableScoping)) {
         // Copy over the Idps that are allowed to answer this request.
         $sspRequest->setIDPList($originalRequest->getIDPList());
         // Proxy Count
         $sspRequest->setProxyCount($originalRequest->getProxyCount() ? $originalRequest->getProxyCount() : $server->getConfig('max_proxies', 10));
         // Add the SP to the requesterIds
         $requesterIds = $originalRequest->getRequesterID();
         $requesterIds[] = $originalRequest->getIssuer();
         // Add the SP as the requester
         $sspRequest->setRequesterID($requesterIds);
     }
     // Use the default binding even if more exist
     $request = new EngineBlock_Saml2_AuthnRequestAnnotationDecorator($sspRequest);
     $request->setDeliverByBinding($idpMetadata->singleSignOnServices[0]->binding);
     return $request;
 }
 /**
  * Get the metadata for a requester, if allowed by the configuration.
  *
  * @param ServiceProvider $serviceProvider
  * @param EngineBlock_Saml2_AuthnRequestAnnotationDecorator $request
  * @param MetadataRepositoryInterface $repository
  * @return null|ServiceProvider
  */
 public static function findRequesterServiceProvider(ServiceProvider $serviceProvider, EngineBlock_Saml2_AuthnRequestAnnotationDecorator $request, MetadataRepositoryInterface $repository)
 {
     if (!$serviceProvider->isTrustedProxy) {
         return null;
     }
     if (!$request->wasSigned()) {
         return null;
     }
     // Requester IDs are appended to as they pass through a proxy, so we always want the last RequesterID
     // Note that this is not specified in the spec, but this is what we do and what SSP does.
     $requesterIds = $request->getRequesterIds();
     $lastRequesterEntityId = end($requesterIds);
     if (!$lastRequesterEntityId) {
         return null;
     }
     $lastRequesterEntity = $repository->findServiceProviderByEntityId($lastRequesterEntityId);
     if (!$lastRequesterEntity) {
         throw new EngineBlock_Exception_DissimilarServiceProviderWorkflowStates($serviceProvider, $lastRequesterEntityId);
     }
     return $lastRequesterEntity;
 }
 protected function _getNameIdFormat(EngineBlock_Saml2_AuthnRequestAnnotationDecorator $request, ServiceProvider $spEntityMetadata)
 {
     // If a NameIDFormat was explicitly set in the ServiceRegistry, use that...
     if ($spEntityMetadata->nameIdFormat) {
         return $spEntityMetadata->nameIdFormat;
     }
     // If the SP requests a specific NameIDFormat in their AuthnRequest
     /** @var SAML2_AuthnRequest $request */
     $nameIdPolicy = $request->getNameIdPolicy();
     if (!empty($nameIdPolicy['Format'])) {
         $mayUseRequestedNameIdFormat = true;
         $requestedNameIdFormat = $nameIdPolicy['Format'];
         // Do we support the NameID Format that the SP requests?
         if (!in_array($requestedNameIdFormat, $this->SUPPORTED_NAMEID_FORMATS)) {
             EngineBlock_ApplicationSingleton::getLog()->notice("Whoa, SP '{$spEntityMetadata->entityId}' requested '{$requestedNameIdFormat}' " . "however we don't support that format, opting to try something else it supports " . "instead of sending an error. SP might not be happy with this violation of the spec " . "but it's probably a lot happier with a valid Response than an Error Response");
             $mayUseRequestedNameIdFormat = false;
         }
         // Is this SP restricted to specific NameIDFormats?
         if (!empty($spEntityMetadata->supportedNameIdFormats)) {
             if (!in_array($requestedNameIdFormat, $spEntityMetadata->supportedNameIdFormats)) {
                 EngineBlock_ApplicationSingleton::getLog()->notice("Whoa, SP '{$spEntityMetadata->entityId}' requested '{$requestedNameIdFormat}' " . "opting to try something else it supports " . "instead of sending an error. SP might not be happy with this violation of the spec " . "but it's probably a lot happier with a valid Response than an Error Response");
                 $mayUseRequestedNameIdFormat = false;
             }
         }
         if ($mayUseRequestedNameIdFormat) {
             return $requestedNameIdFormat;
         }
     }
     // So neither a NameIDFormat is explicitly set in the metadata OR a (valid) NameIDPolicy is set in the AuthnRequest
     // so we check what the SP supports (or what JANUS claims that it supports) and
     // return the least privacy sensitive one.
     if (!empty($spEntityMetadata->supportedNameIdFormats)) {
         foreach ($this->SUPPORTED_NAMEID_FORMATS as $supportedNameIdFormat) {
             if (in_array($supportedNameIdFormat, $spEntityMetadata->supportedNameIdFormats)) {
                 return $supportedNameIdFormat;
             }
         }
     }
     throw new EngineBlock_Exception("Whoa, SP '{$spEntityMetadata->entityId}' has no NameIDFormat set, did send a (valid) NameIDPolicy and has no supported NameIDFormats set... I give up...", EngineBlock_Exception::CODE_NOTICE);
 }
 protected function _showWayf(EngineBlock_Saml2_AuthnRequestAnnotationDecorator $request, array $candidateIdpEntityIds)
 {
     // Post to the 'continueToIdp' service
     $action = $this->_server->getUrl('continueToIdP');
     $serviceProvider = $this->_server->getRepository()->fetchServiceProviderByEntityId($request->getIssuer());
     $idpList = $this->_transformIdpsForWAYF($candidateIdpEntityIds, $request->isDebugRequest());
     $output = $this->_server->renderTemplate('discover', array('preselectedIdp' => $this->_server->getCookie('selectedIdp'), 'action' => $action, 'ID' => $request->getId(), 'idpList' => $idpList, 'metaDataSP' => $serviceProvider));
     $this->_server->sendOutput($output);
 }
 /**
  * @param $ebRequest
  */
 protected function _annotateRequestWithKeyId(EngineBlock_Saml2_AuthnRequestAnnotationDecorator $ebRequest)
 {
     $keyId = $this->_server->getKeyId();
     if (!$keyId) {
         return;
     }
     $ebRequest->setKeyId($keyId);
 }
 /**
  * @param EngineBlock_Saml2_AuthnRequestAnnotationDecorator $fromRequest
  * @param EngineBlock_Saml2_AuthnRequestAnnotationDecorator $toRequest
  * @return $this
  */
 public function link(EngineBlock_Saml2_AuthnRequestAnnotationDecorator $fromRequest, EngineBlock_Saml2_AuthnRequestAnnotationDecorator $toRequest)
 {
     // Store the mapping from the new request ID to the original request ID
     $this->linkStorage[$fromRequest->getId()] = $toRequest->getId();
     return $this;
 }
 public function sendResponseToRequestIssuer(EngineBlock_Saml2_AuthnRequestAnnotationDecorator $request, EngineBlock_Saml2_ResponseAnnotationDecorator $response)
 {
     /** @var SAML2_AuthnRequest $request */
     $requestIssuer = $request->getIssuer();
     $serviceProvider = $this->getRepository()->fetchServiceProviderByEntityId($requestIssuer);
     // Detect error responses and send them off without an assertion.
     /** @var SAML2_Response $response */
     $status = $response->getStatus();
     if ($status['Code'] !== 'urn:oasis:names:tc:SAML:2.0:status:Success') {
         $response->setAssertions(array());
         $this->getBindingsModule()->send($response, $serviceProvider);
         return;
     }
     $this->filterOutputAssertionAttributes($response, $request);
     $this->getBindingsModule()->send($response, $serviceProvider);
 }