/** * @param \Thruway\Event\MessageEvent $event */ public function handleHelloMessageEvent(MessageEvent $event) { $session = $event->session; /** @var HelloMessage $msg */ $msg = $event->message; if ($session->isAuthenticated()) { return; } $session->setAuthenticated(true); // still set admin on trusted transports $authDetails = AuthenticationDetails::createAnonymous(); if ($session->getTransport() !== null && $session->getTransport()->isTrusted()) { $authDetails->addAuthRole('admin'); } $session->setAuthenticationDetails($authDetails); $session->sendMessage(new WelcomeMessage($session->getSessionId(), $msg->getDetails())); }
/** * Process HelloMessage * * @param \Thruway\Session $session * @param \Thruway\Message\HelloMessage $msg * @throws InvalidRealmNameException */ private function processHello(Session $session, HelloMessage $msg) { if ($this->getRealmName() != $msg->getRealm()) { throw new InvalidRealmNameException(); } Logger::debug($this, "Got Hello"); // send welcome message if ($this->sessions->contains($session)) { Logger::error($this, "Connection tried to rejoin realm when it is already joined to the realm."); // shutdown session here because it is obvious we are just on a different // page than the client - maybe we should send abort? $session->shutdown(); } else { $this->sessions->attach($session); $session->setRealm($this); $session->setState(Session::STATE_UP); // this should probably be after authentication if ($this->getAuthenticationManager() !== null) { try { $this->getAuthenticationManager()->onAuthenticationMessage($this, $session, $msg); } catch (\Exception $e) { } } else { $session->setAuthenticated(true); // still set admin on trusted transports $authDetails = AuthenticationDetails::createAnonymous(); if ($session->getTransport() !== null && $session->getTransport()->isTrusted()) { $authDetails->addAuthRole('admin'); } $session->setAuthenticationDetails($authDetails); // the broker and dealer should give us this information $roles = ["broker" => new \stdClass(), "dealer" => new \stdClass()]; $session->sendMessage(new WelcomeMessage($session->getSessionId(), ["roles" => $roles])); } } }
/** * 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 the authmethods and try to send a response message foreach ($this->authMethods as $authMethod => $authMethodInfo) { if (in_array($authMethod, $requestedMethods) && (in_array($realm->getRealmName(), $authMethodInfo['auth_realms']) || in_array("*", $authMethodInfo['auth_realms']))) { $this->onHelloAuthHandler($authMethod, $authMethodInfo, $realm, $session, $msg); $sentMessage = true; } } //If we already replied with a message, we don't have to do anything else if ($sentMessage) { return; } // If no authentication providers are registered for this realm send an abort message if ($this->realmHasAuthProvider($realm->getRealmName())) { $session->abort(new \stdClass(), "wamp.error.not_authorized"); return; } //If we've gotten this far, it means that the user needs to be Logged in as anonymous $session->setAuthenticationDetails(AuthenticationDetails::createAnonymous()); $details = new \stdClass(); $session->sendMessage(new WelcomeMessage($session->getSessionId(), $details)); $session->setAuthenticated(true); }
/** * 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); } } }
/** * @param Session $session * @param Message $msg */ public function onMessage(Session $session, Message $msg) { if (!$session->isAuthenticated()) { if ($msg instanceof HelloMessage) { $this->manager->debug("got hello"); // send welcome message if ($this->sessions->contains($session)) { $this->manager->error("Connection tried to rejoin realm when it is already joined to the realm."); $session->sendMessage(ErrorMessage::createErrorMessageFromMessage($msg)); // TODO should shut down session here } else { $this->sessions->attach($session); $session->setRealm($this); $session->setState(Session::STATE_UP); // this should probably be after authentication if ($this->getAuthenticationManager() !== null) { $this->getAuthenticationManager()->onAuthenticationMessage($this, $session, $msg); } else { $session->setAuthenticated(true); $session->setAuthenticationDetails(AuthenticationDetails::createAnonymous()); // the broker and dealer should give us this information $roles = array("broker" => new \stdClass(), "dealer" => new \stdClass()); $session->sendMessage(new WelcomeMessage($session->getSessionId(), array("roles" => $roles))); } } } else { if ($msg instanceof AuthenticateMessage) { if ($this->getAuthenticationManager() !== null) { $this->getAuthenticationManager()->onAuthenticationMessage($this, $session, $msg); } else { // TODO: should shut down here probably $this->manager->error("Authenticate sent to realm without auth manager."); } } else { $this->manager->error("Unhandled message sent to unauthenticated realm: " . $msg->getMsgCode()); $session->sendMessage(new AbortMessage(new \stdClass(), "wamp.error.not_authorized")); $session->shutdown(); } } } else { $handled = false; /* @var $role AbstractRole */ foreach ($this->roles as $role) { if ($role->handlesMessage($msg)) { $role->onMessage($session, $msg); $handled = true; break; } } if (!$handled) { $this->manager->warning("Unhandled message sent to \"{$this->getRealmName()}\": {$msg->getSerializedMessage()}"); } } }