Beispiel #1
0
 /**
  * @return bdApi_Template_Helper_Core
  */
 public static function getInstance()
 {
     if (self::$_instance === null) {
         $templateHelperClass = XenForo_Application::resolveDynamicClass(__CLASS__, 'bdapi_template_helper');
         self::$_instance = new $templateHelperClass();
     }
     return self::$_instance;
 }
Beispiel #2
0
 public function renderHtml()
 {
     if (!empty($this->_params['tokens'])) {
         foreach ($this->_params['tokens'] as &$token) {
             $token['_scopes'] = bdApi_Template_Helper_Core::getInstance()->scopeSplit($token['scope']);
         }
     }
 }
Beispiel #3
0
 public function updateUserScopes($token)
 {
     $userScopes = $this->getUserScopes($token['client_id'], $token['user_id']);
     $scopes = bdApi_Template_Helper_Core::getInstance()->scopeSplit($token['scope']);
     foreach ($scopes as $scope) {
         if (!isset($userScopes[$scope])) {
             $this->_getDb()->insert('xf_bdapi_user_scope', array('client_id' => $token['client_id'], 'user_id' => $token['user_id'], 'scope' => $scope, 'accept_date' => XenForo_Application::$time));
         }
     }
 }
Beispiel #4
0
 public function renderHtml()
 {
     $this->_params['authorizeScopes'] = array();
     if (!empty($this->_params['authorizeParams']['scope'])) {
         $this->_params['authorizeScopes'] = bdApi_Template_Helper_Core::getInstance()->scopeSplit($this->_params['authorizeParams']['scope']);
     }
     $this->_params['authorizeRedirectUri'] = '';
     if (!empty($this->_params['authorizeParams']['redirect_uri'])) {
         $this->_params['authorizeRedirectUri'] = $this->_params['authorizeParams']['redirect_uri'];
     }
 }
Beispiel #5
0
 public function canAutoAuthorize($client, $scopes)
 {
     $scopeArray = bdApi_Template_Helper_Core::getInstance()->scopeSplit($scopes);
     foreach ($scopeArray as $scope) {
         if (empty($client['options']['auto_authorize'][$scope])) {
             // at least one scope requested is missing
             // CANNOT auto authorize this set of scopes
             return false;
         }
     }
     return true;
 }
Beispiel #6
0
 public function hasScope($client, $token, $scope)
 {
     $helper = bdApi_Template_Helper_Core::getInstance();
     $scopeArray = $helper->scopeSplit($scope);
     $tokenScopeArray = $helper->scopeSplit($token['scope']);
     foreach ($scopeArray as $scopeSingle) {
         // use simple in_array check here without any normalization
         if (!in_array($scopeSingle, $tokenScopeArray)) {
             return false;
         }
     }
     return true;
 }
Beispiel #7
0
 public static function init_dependencies(XenForo_Dependencies_Abstract $dependencies, array $data)
 {
     // initializes the core template helper object
     // in the future, we may have different template helpers for public/admin/api context
     $templateHelper = bdApi_Template_Helper_Core::getInstance();
     // register the helper methods in the format `bdApi_<method_name>`
     $templateHelperReflector = new ReflectionClass(get_class($templateHelper));
     $methods = $templateHelperReflector->getMethods();
     foreach ($methods as $method) {
         if (!($method->getModifiers() & ReflectionMethod::IS_PUBLIC) or $method->getModifiers() & ReflectionMethod::IS_STATIC) {
             // ignore non-public instance methods
             continue;
         }
         $methodName = $method->getName();
         $helperCallbackName = utf8_strtolower('api_' . $methodName);
         XenForo_Template_Helper_Core::$helperCallbacks[$helperCallbackName] = array($templateHelper, $methodName);
     }
 }
Beispiel #8
0
 public static function init_dependencies(XenForo_Dependencies_Abstract $dependencies, array $data)
 {
     // initializes the core template helper object
     // in the future, we may have different template helpers for public/admin/api context
     $templateHelper = bdApi_Template_Helper_Core::getInstance();
     // register the helper methods in the format `bdApi_<method_name>`
     $templateHelperReflector = new ReflectionClass(get_class($templateHelper));
     $methods = $templateHelperReflector->getMethods();
     foreach ($methods as $method) {
         if (!($method->getModifiers() & ReflectionMethod::IS_PUBLIC) || $method->getModifiers() & ReflectionMethod::IS_STATIC) {
             // ignore restricted or static methods
             continue;
         }
         $methodName = $method->getName();
         $helperCallbackName = utf8_strtolower('api_' . $methodName);
         XenForo_Template_Helper_Core::$helperCallbacks[$helperCallbackName] = array($templateHelper, $methodName);
     }
     XenForo_CacheRebuilder_Abstract::$builders['bdApi_CacheRebuilder_ClientContentDeleteAll'] = 'bdApi_CacheRebuilder_ClientContentDeleteAll';
     bdApi_ShippableHelper_Updater::onInitDependencies($dependencies, bdApi_Option::UPDATER_URL);
 }
Beispiel #9
0
 public function actionAdd()
 {
     if ($this->isConfirmedPost()) {
         $clientId = $this->_input->filterSingle('client_id', XenForo_Input::STRING);
         $client = $this->_getClientOrError($clientId);
         $username = $this->_input->filterSingle('username', XenForo_Input::STRING);
         /* @var $userModel XenForo_Model_User */
         $userModel = $this->getModelFromCache('XenForo_Model_User');
         $user = $userModel->getUserByName($username);
         if (empty($user)) {
             return $this->responseError(new XenForo_Phrase('requested_user_not_found'), 404);
         }
         $scopes = $this->_input->filterSingle('scopes', XenForo_Input::ARRAY_SIMPLE);
         $scopes = bdApi_Template_Helper_Core::getInstance()->scopeJoin($scopes);
         $ttl = $this->_input->filterSingle('ttl', XenForo_Input::UINT);
         $this->_getOAuth2Model()->getServer()->createAccessToken($client['client_id'], $user['user_id'], $scopes, $ttl, false);
         return $this->responseRedirect(XenForo_ControllerResponse_Redirect::SUCCESS, XenForo_Link::buildAdminLink('api-tokens'));
     } else {
         $viewParams = array('clients' => $this->_getClientModel()->getList(), 'scopes' => $this->_getOAuth2Model()->getSystemSupportedScopes());
         return $this->responseView('bdApi_ViewAdmin_Token_Add', 'bdapi_token_add', $viewParams);
     }
 }
Beispiel #10
0
 public function getAutoAndUserScopes($clientId, $userId)
 {
     $client = $this->getClientModel()->getClientById($clientId);
     if (empty($client)) {
         return '';
     }
     $scopes = array();
     if (!empty($client['options']['auto_authorize'])) {
         foreach ($client['options']['auto_authorize'] as $scope => $canAutoAuthorize) {
             if ($canAutoAuthorize) {
                 $scopes[] = $scope;
             }
         }
     }
     $userScopes = $this->getUserScopeModel()->getUserScopes($client['client_id'], $userId);
     if (!empty($userScopes)) {
         foreach ($userScopes as $scope => $userScope) {
             $scopes[] = $scope;
         }
         $scopes = array_unique($scopes);
     }
     return bdApi_Template_Helper_Core::getInstance()->scopeJoin($scopes);
 }
Beispiel #11
0
 public function actionAuthorize()
 {
     /* @var $oauth2Model bdApi_Model_OAuth2 */
     $oauth2Model = $this->getModelFromCache('bdApi_Model_OAuth2');
     $authorizeParams = $this->_input->filter($oauth2Model->getAuthorizeParamsInputFilter());
     if ($this->_request->isPost()) {
         // allow user to deny some certain scopes
         // only when this is a POST request, this should keep us safe from some vectors
         // of attack
         $scopesIncluded = $this->_input->filterSingle('scopes_included', XenForo_Input::UINT);
         $scopes = $this->_input->filterSingle('scopes', XenForo_Input::ARRAY_SIMPLE);
         if (!empty($scopesIncluded)) {
             $authorizeParams['scope'] = bdApi_Template_Helper_Core::getInstance()->scopeJoin($scopes);
         }
     }
     $client = $oauth2Model->getClientModel()->getClientById($authorizeParams['client_id']);
     if (empty($client)) {
         throw new XenForo_Exception(new XenForo_Phrase('bdapi_authorize_error_client_x_not_found', array('client' => $authorizeParams['client_id'])));
     }
     // sondh@2013-03-19
     // this is a non-standard implementation: bypass confirmation dialog if the
     // client has appropriate option set
     $bypassConfirmation = false;
     if ($oauth2Model->getClientModel()->canAutoAuthorize($client, $authorizeParams['scope'])) {
         $bypassConfirmation = true;
     }
     // sondh@2014-09-26
     // bypass confirmation if all requested scopes have been granted at some point
     // in old version of this add-on, it checked for scope from active tokens
     // from now on, we look for all scopes (no expiration) for better user experience
     // if a token expires, it should not invalidate all user's choices
     $userScopes = $oauth2Model->getUserScopeModel()->getUserScopes($client['client_id'], XenForo_Visitor::getUserId());
     $paramScopes = bdApi_Template_Helper_Core::getInstance()->scopeSplit($authorizeParams['scope']);
     $paramScopesNew = array();
     foreach ($paramScopes as $paramScope) {
         if (!isset($userScopes[$paramScope])) {
             $paramScopesNew[] = $paramScope;
         }
     }
     if (empty($paramScopesNew)) {
         $bypassConfirmation = true;
     } else {
         $authorizeParams['scope'] = bdApi_Template_Helper_Core::getInstance()->scopeJoin($paramScopesNew);
     }
     $response = $oauth2Model->getServer()->actionOauthAuthorize1($this, $authorizeParams);
     if (is_object($response) && $response instanceof XenForo_ControllerResponse_Abstract) {
         return $response;
     }
     if ($this->_request->isPost() || $bypassConfirmation) {
         $accept = $this->_input->filterSingle('accept', XenForo_Input::STRING);
         $accepted = !!$accept;
         if ($bypassConfirmation) {
             // sondh@2013-03-19
             // of course if the dialog was bypassed, $accepted should be true
             $accepted = true;
         }
         if ($accepted) {
             // sondh@2014-09-26
             // get all up to date user scopes and include in the new token
             // that means client only need to ask for a scope once and they will always have
             // that scope in future authorizations, even if they ask for less scope!
             // making it easy for client dev, they don't need to track whether they requested
             // a scope before. Just check the most recent token for that information.
             $paramScopes = bdApi_Template_Helper_Core::getInstance()->scopeSplit($authorizeParams['scope']);
             foreach ($userScopes as $userScope => $userScopeInfo) {
                 if (!in_array($userScope, $paramScopes, true)) {
                     $paramScopes[] = $userScope;
                 }
             }
             $paramScopes = array_unique($paramScopes);
             asort($paramScopes);
             $authorizeParams['scope'] = bdApi_Template_Helper_Core::getInstance()->scopeJoin($paramScopes);
         }
         return $oauth2Model->getServer()->actionOauthAuthorize2($this, $authorizeParams, $accepted, XenForo_Visitor::getUserId());
     } else {
         $viewParams = array('client' => $client, 'authorizeParams' => $authorizeParams);
         return $this->_getWrapper('account', 'api', $this->responseView('bdApi_ViewPublic_Account_Authorize', 'bdapi_account_authorize', $viewParams));
     }
 }
Beispiel #12
0
 public function actionPostIndex()
 {
     /* @var $oauth2Model bdApi_Model_OAuth2 */
     $oauth2Model = $this->getModelFromCache('bdApi_Model_OAuth2');
     /* @var $userConfirmationModel XenForo_Model_UserConfirmation */
     $userConfirmationModel = $this->getModelFromCache('XenForo_Model_UserConfirmation');
     /* @var $session bdApi_Session */
     $session = XenForo_Application::getSession();
     $clientId = $session->getOAuthClientId();
     $clientSecret = $session->getOAuthClientSecret();
     if (empty($clientId) or empty($clientSecret)) {
         $clientId = $this->_input->filterSingle('client_id', XenForo_Input::STRING);
         $client = $oauth2Model->getClientModel()->getClientById($clientId);
         if (empty($client)) {
             return $this->responseError(new XenForo_Phrase('bdapi_post_slash_users_requires_client_id'), 400);
         }
         $clientSecret = $client['client_secret'];
     }
     $input = $this->_input->filter(array('user_email' => XenForo_Input::STRING, 'username' => XenForo_Input::STRING, 'password' => XenForo_Input::STRING, 'password_algo' => XenForo_Input::STRING, 'user_dob_day' => XenForo_Input::UINT, 'user_dob_month' => XenForo_Input::UINT, 'user_dob_year' => XenForo_Input::UINT));
     if (empty($input['user_email'])) {
         // backward compatibility
         $input['user_email'] = $this->_input->filterSingle('email', XenForo_Input::STRING);
     }
     $extraInput = $this->_input->filter(array('extra_data' => XenForo_Input::STRING, 'extra_timestamp' => XenForo_Input::UINT));
     if (!empty($extraInput['extra_data'])) {
         $extraData = bdApi_Crypt::decryptTypeOne($extraInput['extra_data'], $extraInput['extra_timestamp']);
         if (!empty($extraData)) {
             $extraData = @unserialize($extraData);
         }
         if (empty($extraData)) {
             $extraData = array();
         }
     }
     $userModel = $this->_getUserModel();
     $options = XenForo_Application::getOptions();
     $session = XenForo_Application::getSession();
     $visitor = XenForo_Visitor::getInstance();
     /* @var $writer XenForo_DataWriter_User */
     $writer = XenForo_DataWriter::create('XenForo_DataWriter_User');
     $registrationDefaults = $options->get('registrationDefaults');
     if (!empty($registrationDefaults)) {
         $writer->bulkSet($registrationDefaults, array('ignoreInvalidFields' => true));
     }
     $writer->set('email', $input['user_email']);
     $writer->set('username', $input['username']);
     $password = bdApi_Crypt::decrypt($input['password'], $input['password_algo'], $clientSecret);
     if (!empty($password)) {
         $writer->setPassword($password, $password);
     } else {
         // no password or unable to decrypt password
         // create new user with no password auth scheme
         $auth = XenForo_Authentication_Abstract::create('XenForo_Authentication_NoPassword');
         $writer->set('scheme_class', $auth->getClassName());
         $writer->set('data', $auth->generate(''), 'xf_user_authenticate');
     }
     if ($options->get('gravatarEnable') && XenForo_Model_Avatar::gravatarExists($input['user_email'])) {
         $writer->set('gravatar', $input['user_email']);
     }
     $writer->set('dob_day', $input['user_dob_day']);
     $writer->set('dob_month', $input['user_dob_month']);
     $writer->set('dob_year', $input['user_dob_year']);
     $writer->set('user_group_id', XenForo_Model_User::$defaultRegisteredGroupId);
     $writer->set('language_id', XenForo_Visitor::getInstance()->get('language_id'));
     $allowEmailConfirm = true;
     if (!empty($extraData['user_email']) && $extraData['user_email'] == $writer->get('email')) {
         // the email address has been validated by some other mean (external provider?)
         // do not require email confirmation again to avoid complication
         $allowEmailConfirm = false;
     }
     $writer->advanceRegistrationUserState($allowEmailConfirm);
     if ($visitor->hasAdminPermission('user') and $session->checkScope(bdApi_Model_OAuth2::SCOPE_MANAGE_SYSTEM)) {
         $writer->set('user_state', 'valid');
     }
     $writer->save();
     $user = $writer->getMergedData();
     // log the ip of the user registering
     XenForo_Model_Ip::log(XenForo_Visitor::getUserId() ? XenForo_Visitor::getUserId() : $user['user_id'], 'user', $user['user_id'], 'register');
     if ($user['user_state'] == 'email_confirm') {
         $userConfirmationModel->sendEmailConfirmation($user);
     }
     if (!empty($extraData['external_provider']) && !empty($extraData['external_provider_key'])) {
         /* @var $userExternalModel XenForo_Model_UserExternal */
         $userExternalModel = $this->getModelFromCache('XenForo_Model_UserExternal');
         $userExternalModel->updateExternalAuthAssociation($extraData['external_provider'], $extraData['external_provider_key'], $user['user_id']);
     }
     if (XenForo_Visitor::getUserId() == 0) {
         XenForo_Visitor::setup($user['user_id']);
     }
     $scopes = $oauth2Model->getSystemSupportedScopes();
     $scopes = bdApi_Template_Helper_Core::getInstance()->scopeJoin($scopes);
     $token = $oauth2Model->getServer()->createAccessToken($clientId, $user['user_id'], $scopes);
     $user = $userModel->getUserById($user['user_id'], $userModel->getFetchOptionsToPrepareApiData());
     $data = array('user' => $this->_filterDataSingle($this->_getUserModel()->prepareApiDataForUser($user)), '_user' => $user, 'token' => $token);
     return $this->responseData('bdApi_ViewApi_User_Single', $data);
 }
Beispiel #13
0
 public function actionApiData()
 {
     /* @var $clientModel bdApi_Model_Client */
     $clientModel = $this->getModelFromCache('bdApi_Model_Client');
     /* @var $userScopeModel bdApi_Model_UserScope */
     $userScopeModel = $this->getModelFromCache('bdApi_Model_UserScope');
     /* @var $userModel bdApi_XenForo_Model_User */
     $userModel = $this->getModelFromCache('XenForo_Model_User');
     $callback = $this->_input->filterSingle('callback', XenForo_Input::STRING);
     $cmd = $this->_input->filterSingle('cmd', XenForo_Input::STRING);
     $clientId = $this->_input->filterSingle('client_id', XenForo_Input::STRING);
     $data = array();
     $data[$cmd] = 0;
     $client = $clientModel->getClientById($clientId);
     $visitorObj = XenForo_Visitor::getInstance();
     $visitorArray = $visitorObj->toArray();
     if (!empty($client) and $visitorArray['user_id'] > 0) {
         switch ($cmd) {
             case 'authorized':
                 $scope = $this->_input->filterSingle('scope', XenForo_Input::STRING);
                 $requestedScopes = bdApi_Template_Helper_Core::getInstance()->scopeSplit($scope);
                 if (empty($requestedScopes)) {
                     // no scope requested, check for scope `read`
                     $requestedScopes[] = bdApi_Model_OAuth2::SCOPE_READ;
                 }
                 $requestedScopesAccepted = array();
                 if ($data[$cmd] === 0 and $clientModel->canAutoAuthorize($client, $scope)) {
                     // this client has auto authorize setting for the requested scope
                     // response with authorized = 1
                     // note: we don't have (and don't need) an access token for now
                     // but in case the client application request authorization, it
                     // will be granted automatically anyway
                     $requestedScopesAccepted = $requestedScopes;
                     $data[$cmd] = 1;
                 }
                 if ($data[$cmd] === 0) {
                     // start looking for accepted scopes
                     $userScopes = $userScopeModel->getUserScopes($client['client_id'], $visitorArray['user_id']);
                     foreach ($requestedScopes as $scope) {
                         foreach ($userScopes as $userScope) {
                             if ($userScope['scope'] === $scope) {
                                 $requestedScopesAccepted[] = $scope;
                             }
                         }
                     }
                     if (count($requestedScopes) === count($requestedScopesAccepted)) {
                         $data[$cmd] = 1;
                     }
                 }
                 if ($data[$cmd] === 1) {
                     if (!empty($scope)) {
                         // some actual scopes were requested, return user data according to those scopes
                         $session = new bdApi_Session();
                         $session->fakeStart($client, $visitorObj, $requestedScopesAccepted);
                         $visitorPrepared = $userModel->prepareApiDataForUser($visitorArray);
                         $data = array_merge($visitorPrepared, $data);
                     } else {
                         // just checking for connection status, return user_id only
                         $data['user_id'] = $visitorArray['user_id'];
                     }
                 }
                 // switch ($cmd)
                 break;
         }
     }
     $clientModel->signApiData($client, $data);
     $viewParams = array('callback' => $callback, 'cmd' => $cmd, 'client_id' => $clientId, 'data' => $data);
     $this->_routeMatch->setResponseType('raw');
     return $this->responseView('bdApi_ViewPublic_Misc_Api_Data', '', $viewParams);
 }
Beispiel #14
0
 public function getScope()
 {
     $storage = $this->storage;
     if ($storage instanceof bdApi_OAuth2_Storage) {
         if ($this->getUserId() > 0) {
             return $storage->getModel()->getAutoAndUserScopes($this->getClientId(), $this->getUserId());
         } else {
             return bdApi_Template_Helper_Core::getInstance()->scopeJoin($storage->getModel()->getSystemSupportedScopes());
         }
     }
     return '';
 }
Beispiel #15
0
 public function fakeStart(array $client, XenForo_Visitor $visitor, array $scopes)
 {
     $this->_oauthToken = array('token_id' => 0, 'client_id' => $client['client_id'], 'token_text' => '', 'expire_date' => XenForo_Application::$time, 'issue_date' => XenForo_Application::$time, 'user_id' => $visitor['user_id'], 'scope' => bdApi_Template_Helper_Core::getInstance()->scopeJoin($scopes));
     $this->changeUserId($visitor['user_id']);
     $this->set('scopes', $scopes);
     XenForo_Application::set('_bdApi_session', $this);
 }
Beispiel #16
0
 public function actionAuthorize()
 {
     /* @var $oauth2Model bdApi_Model_OAuth2 */
     $oauth2Model = $this->getModelFromCache('bdApi_Model_OAuth2');
     $authorizeParams = $this->_input->filter($oauth2Model->getAuthorizeParamsInputFilter());
     if ($this->_request->isPost()) {
         // allow user to deny some certain scopes
         // only when this is a POST request, this should keep us safe from some vectors
         // of attack
         $scopesIncluded = $this->_input->filterSingle('scopes_included', XenForo_Input::UINT);
         $scopes = $this->_input->filterSingle('scopes', XenForo_Input::ARRAY_SIMPLE);
         if (!empty($scopesIncluded)) {
             $authorizeParams['scope'] = bdApi_Template_Helper_Core::getInstance()->scopeJoin($scopes);
         }
     }
     $client = null;
     $clientIsAuto = false;
     if (empty($authorizeParams['client_id'])) {
         // try to get the first client of user if available
         $visitorClients = $this->_bdApi_getClientModel()->getClients(array('user_id' => XenForo_Visitor::getUserId()), array('limit' => 1));
         if (!empty($visitorClients)) {
             $randClientId = array_rand($visitorClients, 1);
             $client = $visitorClients[$randClientId];
             $clientIsAuto = true;
             $authorizeParams['client_id'] = $client['client_id'];
             // auto assign at least the READ scope
             if (empty($authorizeParams['scope'])) {
                 $authorizeParams['scope'] = bdApi_Model_OAuth2::SCOPE_READ;
             }
             // reset the redirect uri to prevent security issue
             $authorizeParams['redirect_uri'] = '';
             // force to use implicit authentication flow2
             $authorizeParams['response_type'] = 'token';
         }
     } else {
         $client = $oauth2Model->getClientModel()->getClientById($authorizeParams['client_id']);
     }
     if (empty($client)) {
         if (XenForo_Visitor::getInstance()->hasPermission('general', 'bdApi_clientNew')) {
             return $this->responseError(new XenForo_Phrase('bdapi_authorize_no_client_create_one_question', array('link' => XenForo_Link::buildPublicLink('account/api/client-add'))), 404);
         }
         return $this->responseError(new XenForo_Phrase('bdapi_authorize_error_client_x_not_found', array('client' => $authorizeParams['client_id'])), 404);
     }
     // sondh@2013-03-19
     // this is a non-standard implementation: bypass confirmation dialog if the
     // client has appropriate option set
     $bypassConfirmation = false;
     if ($oauth2Model->getClientModel()->canAutoAuthorize($client, $authorizeParams['scope'])) {
         $bypassConfirmation = true;
     }
     // sondh@2015-09-28
     // bypass confirmation if user logged in to authorize
     // this is secured by checking our encrypted time-expiring hash
     $hashInput = $this->_input->filter(array('hash' => XenForo_Input::STRING, 'timestamp' => XenForo_Input::UINT));
     if (!empty($hashInput['hash']) && !empty($hashInput['timestamp'])) {
         try {
             if (bdApi_Crypt::decryptTypeOne($hashInput['hash'], $hashInput['timestamp'])) {
                 $bypassConfirmation = true;
             }
         } catch (XenForo_Exception $e) {
             if (XenForo_Application::debugMode()) {
                 $this->_response->setHeader('X-Api-Exception', $e->getMessage());
             }
         }
     }
     // sondh@2014-09-26
     // bypass confirmation if all requested scopes have been granted at some point
     // in old version of this add-on, it checked for scope from active tokens
     // from now on, we look for all scopes (no expiration) for better user experience
     // if a token expires, it should not invalidate all user's choices
     $userScopes = $oauth2Model->getUserScopeModel()->getUserScopes($client['client_id'], XenForo_Visitor::getUserId());
     $paramScopes = bdApi_Template_Helper_Core::getInstance()->scopeSplit($authorizeParams['scope']);
     $paramScopesNew = array();
     foreach ($paramScopes as $paramScope) {
         if (!isset($userScopes[$paramScope])) {
             $paramScopesNew[] = $paramScope;
         }
     }
     if (empty($paramScopesNew)) {
         $bypassConfirmation = true;
     } else {
         $authorizeParams['scope'] = bdApi_Template_Helper_Core::getInstance()->scopeJoin($paramScopesNew);
     }
     // sondh@2015-09-28
     // disable bypassing confirmation for testing purpose
     if ($clientIsAuto) {
         $bypassConfirmation = false;
     }
     $response = $oauth2Model->getServer()->actionOauthAuthorize1($this, $authorizeParams);
     if (is_object($response) && $response instanceof XenForo_ControllerResponse_Abstract) {
         return $response;
     }
     if ($this->_request->isPost() || $bypassConfirmation) {
         $accept = $this->_input->filterSingle('accept', XenForo_Input::STRING);
         $accepted = !!$accept;
         if ($bypassConfirmation) {
             // sondh@2013-03-19
             // of course if the dialog was bypassed, $accepted should be true
             $accepted = true;
         }
         if ($accepted) {
             // sondh@2014-09-26
             // get all up to date user scopes and include in the new token
             // that means client only need to ask for a scope once and they will always have
             // that scope in future authorizations, even if they ask for less scope!
             // making it easy for client dev, they don't need to track whether they requested
             // a scope before. Just check the most recent token for that information.
             $paramScopes = bdApi_Template_Helper_Core::getInstance()->scopeSplit($authorizeParams['scope']);
             foreach ($userScopes as $userScope => $userScopeInfo) {
                 if (!in_array($userScope, $paramScopes, true)) {
                     $paramScopes[] = $userScope;
                 }
             }
             $paramScopes = array_unique($paramScopes);
             asort($paramScopes);
             $authorizeParams['scope'] = bdApi_Template_Helper_Core::getInstance()->scopeJoin($paramScopes);
         }
         return $oauth2Model->getServer()->actionOauthAuthorize2($this, $authorizeParams, $accepted, XenForo_Visitor::getUserId());
     } else {
         $viewParams = array('client' => $client, 'authorizeParams' => $authorizeParams, 'clientIsAuto' => $clientIsAuto);
         return $this->_getWrapper('account', 'api', $this->responseView('bdApi_ViewPublic_Account_Authorize', 'bdapi_account_authorize', $viewParams));
     }
 }