/** * @depends testRealmCreate * * @param \Thruway\Realm $realm * @return \Thruway\Session */ public function testJoin(\Thruway\Realm $realm) { $session = new \Thruway\Session(new \Thruway\Transport\DummyTransport()); $realm->addSession($session); $this->assertSame($session->getRealm(), $realm); return $session; }
/** * Gets called when the module is initialized in the router * * @inheritdoc */ public function initModule(RouterInterface $router, LoopInterface $loop) { parent::initModule($router, $loop); $this->routerRealm = $router->getRealmManager()->getRealm($this->getRealm()); $this->broker = $this->routerRealm->getBroker(); $this->broker->setStateHandlerRegistry($this); }
/** * @depends testRealmCreate * * @param \Thruway\Realm $realm * @return \Thruway\Session */ public function testJoin(\Thruway\Realm $realm) { $session = new \Thruway\Session(new \Thruway\Transport\DummyTransport()); $realm->onMessage($session, new \Thruway\Message\HelloMessage('test_realm', [])); $this->assertInstanceOf('\\Thruway\\Message\\WelcomeMessage', $session->getTransport()->getLastMessageSent()); $this->assertSame($session->getRealm(), $realm); return $session; }
/** * Add new realm * * @param \Thruway\Realm $realm * @throws \Thruway\Exception\InvalidRealmNameException * @throws \Exception */ public function addRealm(Realm $realm) { $realmName = $realm->getRealmName(); if (!static::validRealmName($realm->getRealmName())) { throw new InvalidRealmNameException(); } if (array_key_exists($realm->getRealmName(), $this->realms)) { throw new \Exception("There is already a realm \"" . $realm->getRealmName() . "\""); } Logger::debug($this, "Adding realm \"" . $realmName . "\""); if ($realm->getManager() instanceof ManagerDummy) { /** remind people that we don't setup the manager for them if they * are creating their own realms */ Logger::info($this, "Realm \"" . $realmName . "\" is using ManagerDummy"); } $this->realms[$realm->getRealmName()] = $realm; }
/** * Add new realm * * @param \Thruway\Realm $realm * @throws \Thruway\Exception\InvalidRealmNameException * @throws \Exception */ public function addRealm(Realm $realm) { $realmName = $realm->getRealmName(); if (!static::validRealmName($realm->getRealmName())) { throw new InvalidRealmNameException(); } if (array_key_exists($realm->getRealmName(), $this->realms)) { throw new \Exception("There is already a realm \"" . $realm->getRealmName() . "\""); } Logger::debug($this, "Adding realm \"" . $realmName . "\""); $this->realms[$realm->getRealmName()] = $realm; $this->router->getEventDispatcher()->dispatch('new_realm', new NewRealmEvent($realm)); }
/** * Call the RPC URI that has been registered to handle Authentication Hello Messages * * @param $authMethod * @param $authMethodInfo * @param Realm $realm * @param Session $session * @param HelloMessage $msg */ private function onHelloAuthHandler($authMethod, $authMethodInfo, Realm $realm, Session $session, HelloMessage $msg) { $authDetails = new AuthenticationDetails(); $authDetails->setAuthMethod($authMethod); $helloDetails = $msg->getDetails(); if (isset($helloDetails->authid)) { $authDetails->setAuthId($helloDetails->authid); } $session->setAuthenticationDetails($authDetails); $sessionInfo = ["sessionId" => $session->getSessionId(), "realm" => $realm->getRealmName()]; $onHelloSuccess = function ($res) use($realm, $session, $msg) { // this is handling the return of the onhello RPC call if (isset($res[0]) && $res[0] == "FAILURE") { $session->abort(new \stdClass(), "thruway.error.authentication_failure"); return; } if (count($res) < 2) { $session->abort(new \stdClass(), "thruway.auth.invalid_response_to_hello"); return; } switch ($res[0]) { case "CHALLENGE": // TODO: validate challenge message $authMethod = $res[1]->challenge_method; $challenge = $res[1]->challenge; $session->getAuthenticationDetails()->setChallenge($challenge); $session->getAuthenticationDetails()->setChallengeDetails($res[1]); $challengeDetails = $session->getAuthenticationDetails()->getChallengeDetails(); $session->sendMessage(new ChallengeMessage($authMethod, $challengeDetails)); break; case "NOCHALLENGE": $details = new \stdClass(); $details->authid = $res[1]->authid; $details->authmethod = $session->getAuthenticationDetails()->getAuthMethod(); if (isset($res[1]->_thruway_authextra)) { $session->getAuthenticationDetails()->setAuthExtra($res[1]->_thruway_authextra); } $session->sendMessage(new WelcomeMessage($session->getSessionId(), $details)); break; default: $session->abort(new \stdClass(), "thruway.error.authentication_failure"); } }; $onHelloError = function () use($session) { Logger::error($this, "onhello rejected the promise"); $session->abort("thruway.error.unknown"); }; $onHelloAuthHandler = $authMethodInfo['handlers']->onhello; //Make the OnHello Call $this->session->call($onHelloAuthHandler, [$msg, $sessionInfo])->then($onHelloSuccess, $onHelloError); }
/** * Handle HelloMessage * * @param \Thruway\Realm $realm * @param \Thruway\Session $session * @param \Thruway\Message\HelloMessage $msg */ public function handleHelloMessage(Realm $realm, Session $session, HelloMessage $msg) { $requestedMethods = $msg->getAuthMethods(); $sentMessage = false; // go through our authMethods and see which one matches first foreach ($this->authMethods as $authMethod => $authMethodInfo) { if (in_array($authMethod, $requestedMethods) && (in_array($realm->getRealmName(), $authMethodInfo['auth_realms']) || in_array("*", $authMethodInfo['auth_realms']))) { // we can agree on something $authDetails = new AuthenticationDetails(); $authDetails->setAuthMethod($authMethod); $helloDetails = $msg->getDetails(); if (isset($helloDetails['authid'])) { $authDetails->setAuthId($helloDetails['authid']); } $session->setAuthenticationDetails($authDetails); $sessionInfo = ["sessionId" => $session->getSessionId(), "realm" => $realm->getRealmName()]; $this->session->call($authMethodInfo['handlers']['onhello'], [$msg, $sessionInfo])->then(function ($res) use($session, $msg) { // this is handling the return of the onhello RPC call if (count($res) < 2) { $session->abort(new \stdClass(), "thruway.auth.invalid_response_to_hello"); return; } if ($res[0] == "CHALLENGE") { // TODO: validate challenge message $authMethod = $res[1]['challenge_method']; $challenge = $res[1]['challenge']; $session->getAuthenticationDetails()->setChallenge($challenge); $session->getAuthenticationDetails()->setChallengeDetails($res[1]); $session->sendMessage(new ChallengeMessage($authMethod, $session->getAuthenticationDetails()->getChallengeDetails())); } else { if ($res[0] == "NOCHALLENGE") { $session->sendMessage(new WelcomeMessage($session->getSessionId(), ["authid" => $res[1]["authid"], "authmethod" => $session->getAuthenticationDetails()->getAuthMethod()])); } else { if ($res[0] == "ERROR") { $session->abort(new \stdClass(), "authentication_failure"); } else { $session->abort(new \stdClass(), "authentication_failure"); } } } }, function () use($session) { Logger::error($this, "onhello rejected the promise"); $session->abort("thruway.error.unknown"); }); $sentMessage = true; } } /* * If we've gotten this far without sending a message, it means that no auth methods were sent by the client or the auth method sent * by the client hasn't been registered for this realm, so we need to check if there are any auth providers registered for the realm. * If there are auth provides registered then Abort. Otherwise we can send a welcome message. */ if (!$sentMessage) { if ($this->realmHasAuthProvider($realm->getRealmName())) { $session->abort(new \stdClass(), "wamp.error.not_authorized"); } else { //Logged in as anonymous $session->setAuthenticationDetails(AuthenticationDetails::createAnonymous()); $roles = ["broker" => new \stdClass(), "dealer" => new \stdClass()]; $session->sendMessage(new WelcomeMessage($session->getSessionId(), ["roles" => $roles])); $session->setAuthenticated(true); } } }