request = $request; $this->session = $session; $this->code_check = $code_check; $this->api_wrapper = $api_wrapper; $this->oauth_storage = $oauth_storage; $this->integration_name = $integration_name; $this->rsa_cryptographer_factory = $rsa_cryptographer_factory; } /** * @param null|WP_Error|WP_User $user * * @return bool */ public function supports( $user ) { if ( $this->is_wp_user( $user ) ) { return false; } if ( $this->login_support->has_final_response() ) { return false; } $totp_token = $this->request->post( 'totp_token' ); $status_id = $this->request->post( 'status_id' ); return ! empty( $totp_token ) && ! empty( $status_id ); } /** * @param null|WP_Error|WP_User $user * * @return bool|JSON_Response|Redirection_Response|View_Response */ protected function handle( $user ) { try { $channel_name = $this->get_channel_name(); $totp_token = $this->request->post( 'totp_token' ); $status_id = intval( $this->request->post( 'status_id' ) ); $cryptographer = $this->get_rsa_cryptographer(); $totp_token = explode( '_', $cryptographer->decryptBase64( $totp_token ) ); if ( count( $totp_token ) < 2 ) { $this->api_wrapper->update_channel_status( $channel_name, $status_id, ChannelStatuses::REJECTED ); $this->login_support->set_error( Errors::INVALID_CODE ); return $this->fallback( $user ); } $code = $totp_token[0]; $salt = $totp_token[1]; if ( substr( $channel_name, - 12 ) != $salt ) { $this->api_wrapper->update_channel_status( $channel_name, $status_id, ChannelStatuses::REJECTED ); $this->login_support->set_error( Errors::INVALID_CODE ); return $this->fallback( $user ); } $user_id = $this->get_user_id(); $integration_user = $this->get_integration_user(); if ( is_null( $integration_user ) ) { $this->api_wrapper->update_channel_status( $channel_name, $status_id, ChannelStatuses::REJECTED ); $response = $this->json_error( Errors::INTEGRATION_USER_ERROR, 404 ); $this->login_support->set_final_response( $response ); return $this->fallback( $user ); } $result = $this->code_check->check( $this->request, $integration_user, $code ); if ( $result->accepted() ) { $this->api_wrapper->update_channel_status( $channel_name, $status_id, ChannelStatuses::RESOLVED ); $response = $this->json( array( 'user_id' => $user_id ), 200 ); $this->login_support->set_final_response( $response ); return $this->fallback( $user ); } $this->api_wrapper->update_channel_status( $channel_name, $status_id, ChannelStatuses::REJECTED ); if ( ! $result->canRetry() ) { $this->user_storage->block_user(); $response = $this->json_error( Errors::AUTHENTICATION_LIMIT_ERROR, 403 ); $this->login_support->set_final_response( $response ); return $this->fallback( $user ); } $this->login_support->set_error( Errors::INVALID_CODE ); return $this->fallback( $user ); } catch ( Exception $e ) { $this->capture_exception( $e ); } return $this->fallback( $user ); } /** * @return string * * @throws TokenNotFoundException */ private function get_channel_name() { $token = $this->oauth_storage->retrieveToken( TokenType::WORDPRESS ); $integration_id = $token->getIntegrationId(); $pusher_session_id = $this->session->get( Authenticate_Filter::PUSHER_SESSION_ID_KEY ); return "private-wp_{$integration_id}_{$pusher_session_id}"; } /** * @return RsaCryptographer * * @throws TokenNotFoundException * @throws NotFoundException * @throws Account_Exception */ private function get_rsa_cryptographer() { $integration = $this->get_integration(); return $this->rsa_cryptographer_factory->create( $integration ); } /** * @return Integration * * @throws TokenNotFoundException * @throws NotFoundException * @throws Account_Exception */ private function get_integration() { $token = $this->oauth_storage->retrieveToken( TokenType::WORDPRESS ); $integration_id = $token->getIntegrationId(); $integration = $this->api_wrapper->get_integration( $integration_id ); $expected_name = $this->integration_name->get_name(); $current_name = $integration->getName(); if ( $current_name !== $expected_name ) { $integration->setName( $expected_name ); try { $this->api_wrapper->update_integration( $integration ); } catch ( Account_Exception $e ) { $integration->setName( $current_name ); $this->capture_exception( $e ); } } return $integration; } }