/**
  * @param EngineBlock_Saml2_AuthnRequestAnnotationDecorator $request
  * @param ServiceProvider $remoteEntity
  * @return bool
  */
 protected function _verifyAcsLocation(EngineBlock_Saml2_AuthnRequestAnnotationDecorator $request, ServiceProvider $remoteEntity)
 {
     /** @var SAML2_AuthnRequest $request */
     // show error when acl is given without binding or vice versa
     $acsUrl = $request->getAssertionConsumerServiceURL();
     $acsIndex = $request->getAssertionConsumerServiceIndex();
     $protocolBinding = $request->getProtocolBinding();
     if ($acsUrl xor $protocolBinding) {
         $this->_server->getSessionLog()->error("Incomplete ACS location found in request (missing URL or binding)");
         return false;
     }
     // if none specified, all is ok
     if (!$acsUrl && !$acsIndex) {
         return true;
     }
     $acs = $this->_server->getCustomAssertionConsumer($request, $remoteEntity);
     // acs is only returned on valid and known ACS
     return is_array($acs);
 }
 /**
  * Returns a custom ACS location from request or false when
  * none is specified
  *
  * @param EngineBlock_Saml2_AuthnRequestAnnotationDecorator $request
  * @param ServiceProvider $serviceProvider
  * @return null|\OpenConext\Component\EngineBlockMetadata\IndexedService
  */
 public function getCustomAssertionConsumer(EngineBlock_Saml2_AuthnRequestAnnotationDecorator $request, ServiceProvider $serviceProvider)
 {
     $requestWasSigned = $request->wasSigned();
     /** @var SAML2_AuthnRequest $request */
     // Ignore requests for bindings we don't support for responses.
     if ($request->getProtocolBinding() !== SAML2_Const::BINDING_HTTP_POST) {
         $this->_server->getSessionLog()->notice("ProtocolBinding '{$request->getProtocolBinding()}' requested is not supported, ignoring...");
         return false;
     }
     // Custom ACS Location & ProtocolBinding goes first
     if ($request->getAssertionConsumerServiceURL() && $request->getProtocolBinding()) {
         if ($requestWasSigned) {
             $this->_server->getSessionLog()->info("Using AssertionConsumerServiceLocation '{$request->getAssertionConsumerServiceURL()}' " . "and ProtocolBinding '{$request->getProtocolBinding()}' from signed request. ");
             return new Service($request->getAssertionConsumerServiceURL(), $request->getProtocolBinding());
         } else {
             $requestAcsIsRegisteredInMetadata = false;
             foreach ($serviceProvider->assertionConsumerServices as $entityAcs) {
                 $requestAcsIsRegisteredInMetadata = $entityAcs->location === $request->getAssertionConsumerServiceURL() && $entityAcs->binding === $request->getProtocolBinding();
                 if ($requestAcsIsRegisteredInMetadata) {
                     break;
                 }
             }
             if ($requestAcsIsRegisteredInMetadata) {
                 $this->_server->getSessionLog()->info("Using AssertionConsumerServiceLocation '{$request->getAssertionConsumerServiceURL()}' " . "and ProtocolBinding '{$request->getProtocolBinding()}' from unsigned request, " . "it's okay though, the ACSLocation and Binding were registered in the metadata");
                 return new Service($request->getAssertionConsumerServiceURL(), $request->getProtocolBinding());
             } else {
                 $this->_server->getSessionLog()->notice("AssertionConsumerServiceLocation '{$request->getAssertionConsumerServiceURL()}' " . "and ProtocolBinding '{$request->getProtocolBinding()}' were mentioned in request, " . "but the AuthnRequest was not signed, and the ACSLocation and Binding were not found in " . "the metadata for the SP, so I am disallowed from acting upon it." . "Trying the default endpoint..");
             }
         }
         return false;
     } else {
         if ($request->getAssertionConsumerServiceURL() || $request->getProtocolBinding()) {
             // Note that an SP is not actually required to supply both a URL and a Binding.
             // But what should we do if we don't have both? Pick out a random counterpart from the metadata?
             // Seems a little hard to predict for the SP, so we go with the default endpoint.
             $this->_server->getSessionLog()->notice("AssertionConsumerServiceLocation '{$request->getAssertionConsumerServiceURL()}' " . "or ProtocolBinding '{$request->getProtocolBinding()}' were mentioned in request, " . "but not both! Ignoring... ");
         }
     }
     if ($request->getAssertionConsumerServiceIndex()) {
         $index = (int) $request->getAssertionConsumerServiceIndex();
         // Find the indexed ACS in the metadata.
         $indexedAssertionConsumerService = null;
         foreach ($serviceProvider->assertionConsumerServices as $assertionConsumerService) {
             if ((int) $assertionConsumerService->serviceIndex === $index) {
                 $indexedAssertionConsumerService = $assertionConsumerService;
                 break;
             }
         }
         if ($indexedAssertionConsumerService) {
             $this->_server->getSessionLog()->info("Using AssertionConsumerServiceIndex '{$index}' from request");
             return $indexedAssertionConsumerService;
         } else {
             $this->_server->getSessionLog()->notice("AssertionConsumerServiceIndex was mentioned in request, but we don't know any ACS by " . "index '{$index}'? Maybe the metadata was updated and we don't have that endpoint yet? " . "Trying the default endpoint..");
         }
     }
 }