/** * @return null|OpenIdDirectGenericErrorResponse|OpenIdAssociationSessionResponse|OpenIdUnencryptedAssociationSessionResponse */ public function handle() { $response = null; try { $assoc_type = $this->current_request->getAssocType(); $session_type = $this->current_request->getSessionType(); $association = $this->association_service->addAssociation(AssociationFactory::getInstance()->buildSessionAssociation($assoc_type, $this->server_configuration_service->getConfigValue("Session.Association.Lifetime"))); $response = new OpenIdUnencryptedAssociationSessionResponse($association->getHandle(), $session_type, $assoc_type, $association->getLifetime(), $association->getSecret()); } catch (InvalidDHParam $exDH) { $response = new OpenIdDirectGenericErrorResponse($exDH->getMessage()); $this->log_service->error($exDH); } catch (InvalidArgumentException $exDH1) { $response = new OpenIdDirectGenericErrorResponse($exDH1->getMessage()); $this->log_service->error($exDH1); } catch (RuntimeException $exDH2) { $response = new OpenIdDirectGenericErrorResponse($exDH2->getMessage()); $this->log_service->error($exDH2); } return $response; }
/** * @return null|OpenIdDirectGenericErrorResponse|\openid\responses\OpenIdAssociationSessionResponse|OpenIdDiffieHellmanAssociationSessionResponse */ public function handle() { $response = null; try { $assoc_type = $this->current_request->getAssocType(); $session_type = $this->current_request->getSessionType(); //DH parameters $public_prime = $this->current_request->getDHModulus(); //p $public_generator = $this->current_request->getDHGen(); //g //get (g ^ xa mod p) where xa is rp secret key $rp_public_key = $this->current_request->getDHConsumerPublic(); //create association $association = $this->association_service->addAssociation(AssociationFactory::getInstance()->buildSessionAssociation($assoc_type, $this->server_configuration_service->getConfigValue("Session.Association.Lifetime"))); $dh = new DiffieHellman($public_prime, $public_generator); $dh->generateKeys(); //server public key (g ^ xb mod p ), where xb is server private key // g ^ (xa * xb) mod p = (g ^ xa) ^ xb mod p = (g ^ xb) ^ xa mod p $shared_secret = $dh->computeSecretKey($rp_public_key, DiffieHellman::FORMAT_NUMBER, DiffieHellman::FORMAT_BTWOC); $hashed_shared_secret = OpenIdCryptoHelper::digest($session_type, $shared_secret); $server_public_key = base64_encode($dh->getPublicKey(DiffieHellman::FORMAT_BTWOC)); $enc_mac_key = base64_encode($association->getSecret() ^ $hashed_shared_secret); $response = new OpenIdDiffieHellmanAssociationSessionResponse($association->getHandle(), $session_type, $assoc_type, $association->getLifetime(), $server_public_key, $enc_mac_key); } catch (InvalidDHParam $exDH) { $response = new OpenIdDirectGenericErrorResponse($exDH->getMessage()); $this->log_service->error($exDH); } catch (InvalidArgumentException $exDH1) { $response = new OpenIdDirectGenericErrorResponse($exDH1->getMessage()); $this->log_service->error($exDH1); } catch (RuntimeException $exDH2) { $response = new OpenIdDirectGenericErrorResponse($exDH2->getMessage()); $this->log_service->error($exDH2); } return $response; }
/** * Create Positive Identity Assertion * implements http://openid.net/specs/openid-authentication-2_0.html#positive_assertions * @return OpenIdPositiveAssertionResponse * @throws InvalidAssociationTypeException */ private function doAssertion() { $currentUser = $this->auth_service->getCurrentUser(); $context = new ResponseContext(); //initial signature params $context->addSignParam(OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_OpEndpoint)); $context->addSignParam(OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm)); $context->addSignParam(OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo)); $context->addSignParam(OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Nonce)); $context->addSignParam(OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_AssocHandle)); $context->addSignParam(OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId)); $context->addSignParam(OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity)); $op_endpoint = $this->server_configuration_service->getOPEndpointURL(); $identity = $this->server_configuration_service->getUserIdentityEndpointURL($currentUser->getIdentifier()); $nonce = $this->nonce_service->generateNonce(); $realm = $this->current_request->getRealm(); $response = new OpenIdPositiveAssertionResponse($op_endpoint, $identity, $identity, $this->current_request->getReturnTo(), $nonce->getRawFormat(), $realm); foreach ($this->extensions as $ext) { $ext->prepareResponse($this->current_request, $response, $context); } //check former assoc handle... if (is_null($assoc_handle = $this->current_request->getAssocHandle()) || is_null($association = $this->association_service->getAssociation($assoc_handle))) { //create private association ... $association = $this->association_service->addAssociation(AssociationFactory::getInstance()->buildPrivateAssociation($realm, $this->server_configuration_service->getConfigValue("Private.Association.Lifetime"))); $response->setAssocHandle($association->getHandle()); if (!empty($assoc_handle)) { $response->setInvalidateHandle($assoc_handle); } } else { if ($association->getType() != IAssociation::TypeSession) { throw new InvalidAssociationTypeException(OpenIdErrorMessages::InvalidAssociationTypeMessage); } $response->setAssocHandle($assoc_handle); } //create signature ... OpenIdSignatureBuilder::build($context, $association->getMacFunction(), $association->getSecret(), $response); /* * To prevent replay attacks, the OP MUST NOT issue more than one verification response for each * authentication response it had previously issued. An authentication response and its matching * verification request may be identified by their "openid.response_nonce" values. * so associate $nonce with signature and realm */ $this->nonce_service->associateNonce($nonce, $response->getSig(), $realm); //do cleaning ... $this->memento_service->clearCurrentRequest(); $this->auth_service->clearUserAuthorizationResponse(); return $response; }
/** * @expectedException \openid\exceptions\ReplayAttackException */ public function testGetPrivateAssociationMustFail_ReplayAttackException() { $cache_stub = new CacheServiceStub(); $this->app->instance(UtilsServiceCatalog::CacheService, $cache_stub); $lock_manager_service_mock = Mockery::mock('utils\\services\\ILockManagerService'); $lock_manager_service_mock->shouldReceive('acquireLock')->times(2); $this->app->instance(UtilsServiceCatalog::LockManagerService, $lock_manager_service_mock); $service = $this->app[OpenIdServiceCatalog::AssociationService]; $assoc = AssociationFactory::getInstance()->buildPrivateAssociation('https://www.test.com/', 3600); $res = $service->addAssociation($assoc); $this->assertTrue(!is_null($res)); $res2 = $service->getAssociation($res->getHandle(), 'https://www.test.com/'); $this->assertTrue(!is_null($res2)); $this->assertTrue($res2->getSecret() === $res->getSecret()); $lock_manager_service_mock->shouldReceive('acquireLock')->once()->andThrow(new UnacquiredLockException()); $service->getAssociation($res->getHandle(), 'https://www.test.com/'); }