Example #1
0
 /**
  * Handle JMAP authentication requests (POST)
  */
 public function processPOST(Request $request, Response $response)
 {
     // decode JMAP request data
     $json_input = json_decode($request->getBodyAsString(), true);
     if ($json_input === null) {
         throw new ProcessorException(400, "Invalid JSON request body");
     }
     $response->setHeader('Content-Type', 'application/json');
     // initial auth request
     if (isset($json_input['username'])) {
         $this->ctrl->emit('jmap:auth:init', [['data' => $json_input, 'processor' => $this]]);
         $methods = [];
         foreach ($this->providers as $provider) {
             $methods = array_merge($methods, $provider->getAuthMethods());
         }
         // start session and generate the loginId
         $this->session->start();
         $this->session->set('Auth\\username', $json_input['username']);
         $result = ['methods' => array_unique($methods), 'loginId' => $this->session->key];
         // add prompt phrase stored in config
         if ($prompt = App::getInstance()->get('Config')->get('auth.prompt')) {
             $result['prompt'] = $prompt;
         }
         $status = 200;
         $this->ctrl->emit('jmap:auth:more', [['result' => &$result, 'status' => &$status, 'processor' => $this]]);
         $response->setBody(json_encode($result));
         $response->setStatus($status);
     } else {
         if (isset($json_input['loginId']) && isset($json_input['type'])) {
             $this->session->start($json_input['loginId']);
             // trigger event AFTER session has been initialized with the continuation token
             $this->ctrl->emit('jmap:auth:continue', [['data' => $json_input, 'processor' => $this]]);
             // validate token (which is the session key) ...
             if ($this->session->key !== $json_input['loginId'] || empty($this->session->get('Auth\\username'))) {
                 $this->ctrl->logger->debug("Invalid session loginId provided", ['input' => $json_input, 'session' => $this->session->key, 'username' => $this->session->get('Auth\\username')]);
                 $this->ctrl->emit('jmap:auth:restart', [['input' => $json_input, 'status' => 410, 'processor' => $this]]);
                 $response->setStatus(410);
                 // Restart authentication
                 return;
             }
             // ...and get username from session
             $json_input['username'] = $this->session->get('Auth\\username');
             $authenticated = false;
             foreach ($this->providers as $provider) {
                 if (self::getAuthMethod($provider, $json_input['type'])) {
                     try {
                         $authenticated = $provider->authenticate($json_input);
                     } catch (AuthenticationAbortedException $e) {
                         break;
                     }
                 }
                 if ($authenticated) {
                     break;
                 }
             }
             // authentication successful
             if ($authenticated && $authenticated instanceof AuthenticatedIdentity) {
                 $authenticated->username = $json_input['username'];
                 // replace session and generate the accessToken
                 $this->session->regenerateId(true);
                 $this->session->set('Auth\\authenticated', time());
                 $this->session->set('Auth\\identity', $authenticated);
                 // send success response
                 $this->sendAuthSuccess($response, $this->session->key);
             } else {
                 // report authentication failure
                 // TODO: create the same response as in initial auth request above
                 $this->ctrl->emit('jmap:auth:failure', [['input' => $json_input, 'status' => 403, 'processor' => $this]]);
                 $response->setStatus(403);
             }
         } else {
             $response->setStatus(401);
         }
     }
 }