/** * 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); } } }