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; }
protected function _sendCachedResponse(EngineBlock_Saml2_AuthnRequestAnnotationDecorator $request, $scopedIdps) { /** @var SAML2_AuthnRequest $request */ if ($request->getForceAuthn()) { return false; } if (!isset($_SESSION['CachedResponses'])) { return false; } $cachedResponses = $_SESSION['CachedResponses']; $requestIssuerEntityId = $request->getIssuer(); // First, if there is scoping, we reject responses from idps not in the list if (count($scopedIdps) > 0) { foreach ($cachedResponses as $key => $cachedResponse) { if (!in_array($cachedResponse['idp'], $scopedIdps)) { unset($cachedResponses[$key]); } } } if (empty($cachedResponses)) { return false; } $cachedResponse = $this->_pickCachedResponse($cachedResponses); if (!$cachedResponse) { return false; } $this->_server->getSessionLog()->info("Cached response found from Idp"); // Note that we would like to repurpose the response, // but that's tricky as it is probably no longer valid (lifetime is usually something like 5 minutes) // so instead we scope the request to that Idp and trust the Idp to do the remembering. $this->_server->sendAuthenticationRequest($request, $cachedResponse['idp']); return true; }