/**
  * 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);
 }
예제 #2
0
 /**
  * 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);
         }
     }
 }