/**
  * @return EngineBlock_Corto_Module_Bindings
  */
 private function mockBindingsModule()
 {
     $spRequest = new SAML2_AuthnRequest();
     $spRequest->setId('SPREQUEST');
     $spRequest->setIssuer('testSp');
     $spRequest = new EngineBlock_Saml2_AuthnRequestAnnotationDecorator($spRequest);
     $ebRequest = new SAML2_AuthnRequest();
     $ebRequest->setId('EBREQUEST');
     $ebRequest = new EngineBlock_Saml2_AuthnRequestAnnotationDecorator($ebRequest);
     $dummyLog = new Psr\Log\NullLogger();
     $authnRequestRepository = new EngineBlock_Saml2_AuthnRequestSessionRepository($dummyLog);
     $authnRequestRepository->store($spRequest);
     $authnRequestRepository->store($ebRequest);
     $authnRequestRepository->link($ebRequest, $spRequest);
     $assertion = new SAML2_Assertion();
     $assertion->setAttributes(array('urn:org:openconext:corto:internal:sp-entity-id' => array('testSp'), 'urn:mace:dir:attribute-def:cn' => array(null)));
     $responseFixture = new SAML2_Response();
     $responseFixture->setInResponseTo('EBREQUEST');
     $responseFixture->setAssertions(array($assertion));
     $responseFixture = new EngineBlock_Saml2_ResponseAnnotationDecorator($responseFixture);
     $responseFixture->setOriginalIssuer('testIdP');
     // Mock bindings module
     /** @var EngineBlock_Corto_Module_Bindings $bindingsModuleMock */
     $bindingsModuleMock = Phake::mock('EngineBlock_Corto_Module_Bindings');
     Phake::when($bindingsModuleMock)->receiveResponse()->thenReturn($responseFixture);
     return $bindingsModuleMock;
 }
 public function serve($serviceName)
 {
     $log = $this->_server->getSessionLog();
     $response = $this->_displayDebugResponse($serviceName);
     if ($response) {
         return;
     }
     /** @var EngineBlock_Saml2_AuthnRequestAnnotationDecorator|SAML2_AuthnRequest $request */
     $request = $this->_getRequest($serviceName);
     $log->info(sprintf("Fetching service provider matching request issuer '%s'", $request->getIssuer()));
     $sp = $this->_server->getRepository()->fetchServiceProviderByEntityId($request->getIssuer());
     // Flush log if an SP in the requester chain has additional logging enabled
     $log->info("Determining whether service provider in chain requires additional logging");
     $isAdditionalLoggingRequired = EngineBlock_SamlHelper::doRemoteEntitiesRequireAdditionalLogging(EngineBlock_SamlHelper::getSpRequesterChain($sp, $request, $this->_server->getRepository()));
     if ($isAdditionalLoggingRequired) {
         $application = EngineBlock_ApplicationSingleton::getInstance();
         $application->flushLog('Activated additional logging for one or more SPs in the SP requester chain');
         $logger = $application->getLogInstance();
         $logger->info('Raw HTTP request', array('http_request' => (string) $application->getHttpRequest()));
     } else {
         $log->info("No additional logging required");
     }
     // validate custom acs-location (only for unsolicited, normal logins
     //  fall back to default ACS location instead of showing error page)
     if ($serviceName === 'unsolicitedSingleSignOnService') {
         if (!$this->_verifyAcsLocation($request, $sp)) {
             throw new EngineBlock_Corto_Exception_InvalidAcsLocation('Unsolicited sign-on service called, but unknown or invalid ACS location requested');
         }
         $log->info('Unsolicited sign-on ACS location verified.');
     }
     // The request may specify it ONLY wants a response from specific IdPs
     // or we could have it configured that the SP may only be serviced by specific IdPs
     $scopedIdps = $this->_getScopedIdPs($request);
     $cacheResponseSent = $this->_sendCachedResponse($request, $scopedIdps);
     if ($cacheResponseSent) {
         return;
     }
     // If the scoped proxycount = 0, respond with a ProxyCountExceeded error
     if ($request->getProxyCount() === 0) {
         $log->info("Request does not allow any further proxying, responding with 'ProxyCountExceeded' status");
         $response = $this->_server->createErrorResponse($request, 'ProxyCountExceeded');
         $this->_server->sendResponseToRequestIssuer($request, $response);
         return;
     }
     // Get all registered Single Sign On Services
     // Note that we could also only get the ones that are allowed for this SP, but we may also want to show
     // those that are not allowed.
     $candidateIDPs = $this->_server->getRepository()->findAllIdentityProviderEntityIds();
     $posOfOwnIdp = array_search($this->_server->getUrl('idpMetadataService'), $candidateIDPs);
     if ($posOfOwnIdp !== false) {
         $log->info("Removed ourselves from the candidate IdP list");
         unset($candidateIDPs[$posOfOwnIdp]);
     }
     // If we have scoping, filter out every non-scoped IdP
     if (count($scopedIdps) > 0) {
         $log->info(sprintf('%d candidate IdPs before scoping', count($candidateIDPs)), array('idps' => array_values($candidateIDPs)));
         $candidateIDPs = array_intersect($scopedIdps, $candidateIDPs);
         $log->info(sprintf('%d candidate IdPs after scoping', count($candidateIDPs)), array('idps' => array_values($candidateIDPs)));
     } else {
         $log->info(sprintf('No IdP scoping required, %d candidate IdPs', count($candidateIDPs)), array('idps' => array_values($candidateIDPs)));
     }
     // 0 IdPs found! Throw an exception.
     if (count($candidateIDPs) === 0) {
         throw new EngineBlock_Corto_Module_Service_SingleSignOn_NoIdpsException('No candidate IdPs found');
     }
     // Exactly 1 candidate found, send authentication request to the first one.
     if (count($candidateIDPs) === 1) {
         $idp = array_shift($candidateIDPs);
         $log->info("Only 1 candidate IdP ('{$idp}'): omitting WAYF, sending authentication request");
         $this->_server->sendAuthenticationRequest($request, $idp);
         return;
     }
     // Multiple IdPs found...
     // > 1 IdPs found, but isPassive attribute given, unable to show WAYF.
     if ($request->getIsPassive()) {
         $log->info('Request is passive, but can be handled by more than one IdP: responding with NoPassive status');
         $response = $this->_server->createErrorResponse($request, 'NoPassive');
         $this->_server->sendResponseToRequestIssuer($request, $response);
         return;
     }
     $authnRequestRepository = new EngineBlock_Saml2_AuthnRequestSessionRepository($log);
     $authnRequestRepository->store($request);
     // Show WAYF
     $log->info("Multiple candidate IdPs: redirecting to WAYF");
     $this->_showWayf($request, $candidateIDPs);
 }
 private function mockGlobals()
 {
     $_POST['ID'] = 'test';
     $_POST['consent'] = 'yes';
     $assertion = new SAML2_Assertion();
     $assertion->setAttributes(array('urn:mace:dir:attribute-def:mail' => '*****@*****.**'));
     $spRequest = new SAML2_AuthnRequest();
     $spRequest->setId('SPREQUEST');
     $spRequest->setIssuer('https://sp.example.edu');
     $spRequest = new EngineBlock_Saml2_AuthnRequestAnnotationDecorator($spRequest);
     $ebRequest = new SAML2_AuthnRequest();
     $ebRequest->setId('EBREQUEST');
     $ebRequest = new EngineBlock_Saml2_AuthnRequestAnnotationDecorator($ebRequest);
     $dummySessionLog = new Psr\Log\NullLogger();
     $authnRequestRepository = new EngineBlock_Saml2_AuthnRequestSessionRepository($dummySessionLog);
     $authnRequestRepository->store($spRequest);
     $authnRequestRepository->store($ebRequest);
     $authnRequestRepository->link($ebRequest, $spRequest);
     $sspResponse = new SAML2_Response();
     $sspResponse->setInResponseTo('EBREQUEST');
     $sspResponse->setAssertions(array($assertion));
     $_SESSION['consent']['test']['response'] = new EngineBlock_Saml2_ResponseAnnotationDecorator($sspResponse);
 }
 public function sendAuthenticationRequest(EngineBlock_Saml2_AuthnRequestAnnotationDecorator $spRequest, $idpEntityId)
 {
     $cookieExpiresStamp = null;
     if (isset($this->_configs['rememberIdp'])) {
         $cookieExpiresStamp = strtotime($this->_configs['rememberIdp']);
     }
     $this->setCookie('selectedIdp', $idpEntityId, $cookieExpiresStamp);
     $originalId = $spRequest->getId();
     $identityProvider = $this->getRepository()->fetchIdentityProviderByEntityId($idpEntityId);
     $ebRequest = EngineBlock_Saml2_AuthnRequestFactory::createFromRequest($spRequest, $identityProvider, $this);
     $newId = $ebRequest->getId();
     // Store the original Request
     $authnRequestRepository = new EngineBlock_Saml2_AuthnRequestSessionRepository($this->_sessionLog);
     $authnRequestRepository->store($spRequest);
     $authnRequestRepository->link($ebRequest, $spRequest);
     $this->getBindingsModule()->send($ebRequest, $identityProvider);
 }