public function actionExternal() { $providerCode = $this->_input->filterSingle('provider', XenForo_Input::STRING); $assocUserId = $this->_input->filterSingle('assoc', XenForo_Input::UINT); $externalCode = $this->_input->filterSingle('code', XenForo_Input::STRING); $redirect = $this->_bdApiConsumer_getRedirect(); $state = $this->_input->filterSingle('state', XenForo_Input::STRING); if (!empty($state)) { // looks like bdApiConsumer_Option::CONFIG_TRACK_AUTHORIZE_URL_STATE has been enabled // attempt to unpack the state data now $stateData = @base64_decode($state); if ($stateData !== false) { $stateData = @json_decode($stateData, true, 2); if ($stateData !== null) { if (isset($stateData['time'])) { $stateData['timeElapsed'] = XenForo_Application::$time - $stateData['time']; } // make it available in server error log (if an error occurs) $_POST['.state'] = $stateData; } } } $provider = bdApiConsumer_Option::getProviderByCode($providerCode); if (empty($provider)) { if (!empty($externalCode)) { // make this available in server error log $_POST['.dynamicRedirect'] = $this->getDynamicRedirect(); // this is one serious error throw new XenForo_Exception('Provider could not be determined'); } else { return $this->responseNoPermission(); } } $externalRedirectUri = XenForo_Link::buildPublicLink('canonical:register/external', false, array('provider' => $providerCode, 'assoc' => $assocUserId ? $assocUserId : false)); if ($this->_input->filterSingle('reg', XenForo_Input::UINT)) { XenForo_Application::get('session')->set(self::SESSION_KEY_REDIRECT, $redirect); $social = $this->_input->filterSingle('social', XenForo_Input::STRING); $requestUrl = bdApiConsumer_Helper_Api::getRequestUrl($provider, $externalRedirectUri, array('social' => $social)); return $this->responseRedirect(XenForo_ControllerResponse_Redirect::RESOURCE_CANONICAL, $requestUrl); } $externalToken = null; if (empty($externalToken)) { $_token = $this->_input->filterSingle('_token', XenForo_Input::STRING); if (!empty($_token)) { $_token = @base64_decode($_token); if (!empty($_token)) { $_token = @json_decode($_token, true); if (!empty($_token)) { $externalToken = $_token; } } } } if (empty($externalToken)) { // there should be `code` at this point... if (empty($externalCode)) { return $this->responseError(new XenForo_Phrase('bdapi_consumer_error_occurred_while_connecting_with_x', array('provider' => $provider['name']))); } $externalToken = bdApiConsumer_Helper_Api::getAccessTokenFromCode($provider, $externalCode, $externalRedirectUri); if (!empty($externalToken)) { $selfRedirect = $this->_request->getRequestUri(); $selfRedirect = preg_replace('#(\\?|&)code=.+(&|$)#', '$1', $selfRedirect); $selfRedirect = preg_replace('#(\\?|&)state=.+(&|$)#', '$1', $selfRedirect); // filter $externalToken keys to make it more lightweight foreach (array_keys($externalToken) as $_key) { if ($_key === 'debug' || substr($_key, 0, 1) === '_') { unset($externalToken[$_key]); } } $selfRedirect .= sprintf('%1$s_token=%2$s', strpos($selfRedirect, '?') === false ? '?' : '&', rawurlencode(base64_encode(json_encode($externalToken)))); // do a self redirect immediately so user won't refresh the page // TODO: improve this return $this->responseRedirect(XenForo_ControllerResponse_Redirect::SUCCESS, $selfRedirect); } } if (empty($externalToken)) { if (!XenForo_Visitor::getUserId()) { // report error only if user hasn't been logged in return $this->responseError(new XenForo_Phrase('bdapi_consumer_error_occurred_while_connecting_with_x', array('provider' => $provider['name']))); } else { // or try to be friendly and just redirect user back to where s/he was return $this->responseRedirect(XenForo_ControllerResponse_Redirect::SUCCESS, $redirect); } } $externalVisitor = bdApiConsumer_Helper_Api::getVisitor($provider, $externalToken['access_token']); if (empty($externalVisitor)) { return $this->responseError(new XenForo_Phrase('bdapi_consumer_error_occurred_while_connecting_with_x', array('provider' => $provider['name']))); } if (empty($externalVisitor['user_email'])) { return $this->responseError(new XenForo_Phrase('bdapi_consumer_x_returned_unknown_error', array('provider' => $provider['name']))); } if (isset($externalVisitor['user_is_valid']) && isset($externalVisitor['user_is_verified'])) { if (empty($externalVisitor['user_is_valid']) || empty($externalVisitor['user_is_verified'])) { return $this->responseError(new XenForo_Phrase('bdapi_consumer_x_account_not_good_standing', array('provider' => $provider['name']))); } } $userModel = $this->_getUserModel(); /** @var bdApiConsumer_XenForo_Model_UserExternal $userExternalModel */ $userExternalModel = $this->_getUserExternalModel(); $existingAssoc = $userExternalModel->getExternalAuthAssociation($userExternalModel->bdApiConsumer_getProviderCode($provider), $externalVisitor['user_id']); $autoRegistered = false; if (empty($existingAssoc)) { $existingAssoc = $this->_bdApiConsumer_autoRegister($provider, $externalToken, $externalVisitor); if (!empty($existingAssoc)) { $autoRegistered = true; } } if ($existingAssoc && $userModel->getUserById($existingAssoc['user_id'])) { XenForo_Application::get('session')->changeUserId($existingAssoc['user_id']); XenForo_Visitor::setup($existingAssoc['user_id']); if (!$autoRegistered) { $userExternalModel->bdApiConsumer_updateExternalAuthAssociation($provider, $externalVisitor['user_id'], $existingAssoc['user_id'], array_merge($externalVisitor, array('token' => $externalToken))); } return $this->responseRedirect(XenForo_ControllerResponse_Redirect::SUCCESS, $redirect); } $existingUser = false; $emailMatch = false; if (XenForo_Visitor::getUserId()) { $existingUser = XenForo_Visitor::getInstance(); } elseif ($assocUserId) { $existingUser = $userModel->getUserById($assocUserId); } if (!$existingUser) { $existingUser = $userModel->getUserByEmail($externalVisitor['user_email']); $emailMatch = true; } if ($existingUser) { // must associate: matching user return $this->responseView('bdApiConsumer_ViewPublic_Register_External', 'bdapi_consumer_register', array('associateOnly' => true, 'provider' => $provider, 'externalToken' => $externalToken, 'externalVisitor' => $externalVisitor, 'existingUser' => $existingUser, 'emailMatch' => $emailMatch, 'redirect' => $redirect)); } if (bdApiConsumer_Option::get('bypassRegistrationActive')) { // do not check for registration active option } else { $this->_assertRegistrationActive(); } $externalVisitor['username'] = bdApiConsumer_Helper_AutoRegister::suggestUserName($externalVisitor['username'], $userModel); return $this->responseView('bdApiConsumer_ViewPublic_Register_External', 'bdapi_consumer_register', array('provider' => $provider, 'externalToken' => $externalToken, 'externalVisitor' => $externalVisitor, 'redirect' => $redirect, 'customFields' => $this->_getFieldModel()->prepareUserFields($this->_getFieldModel()->getUserFields(array('registration' => true)), true), 'timeZones' => XenForo_Helper_TimeZone::getTimeZones(), 'tosUrl' => XenForo_Dependencies_Public::getTosUrl()), $this->_getRegistrationContainerParams()); }
public function actionExternal() { $providerCode = $this->_input->filterSingle('provider', XenForo_Input::STRING); $assocUserId = $this->_input->filterSingle('assoc', XenForo_Input::UINT); $redirect = $this->_input->filterSingle('redirect', XenForo_Input::STRING); $provider = bdApiConsumer_Option::getProviderByCode($providerCode); if (empty($provider)) { // this is one serious error throw new XenForo_Exception('Provider could not be determined'); } $externalRedirectUri = XenForo_Link::buildPublicLink('canonical:register/external', false, array('provider' => $providerCode, 'assoc' => $assocUserId ? $assocUserId : false)); if ($this->_input->filterSingle('reg', XenForo_Input::UINT)) { $redirect = XenForo_Link::convertUriToAbsoluteUri($this->getDynamicRedirect()); XenForo_Application::get('session')->set(self::SESSION_KEY_REDIRECT, $redirect); $social = $this->_input->filterSingle('social', XenForo_Input::STRING); $requestUrl = bdApiConsumer_Helper_Api::getRequestUrl($provider, $externalRedirectUri, array('social' => $social)); return $this->responseRedirect(XenForo_ControllerResponse_Redirect::RESOURCE_CANONICAL, $requestUrl); } // try to use the non-standard query parameter `t` first, // continue exchange code for access token later if that fails $externalCode = $this->_input->filterSingle('code', XenForo_Input::STRING); if (empty($externalCode)) { return $this->responseError(new XenForo_Phrase('bdapi_consumer_error_occurred_while_connecting_with_x', array('provider' => $provider['name']))); } $externalToken = bdApiConsumer_Helper_Api::getAccessTokenFromCode($provider, $externalCode, $externalRedirectUri); if (empty($externalToken)) { return $this->responseError(new XenForo_Phrase('bdapi_consumer_error_occurred_while_connecting_with_x', array('provider' => $provider['name']))); } $externalVisitor = bdApiConsumer_Helper_Api::getVisitor($provider, $externalToken['access_token']); if (empty($externalVisitor)) { return $this->responseError(new XenForo_Phrase('bdapi_consumer_error_occurred_while_connecting_with_x', array('provider' => $provider['name']))); } if (empty($externalVisitor['user_email'])) { return $this->responseError(new XenForo_Phrase('bdapi_consumer_x_returned_unknown_error', array('provider' => $provider['name']))); } if (isset($externalVisitor['user_is_valid']) and isset($externalVisitor['user_is_verified'])) { if (empty($externalVisitor['user_is_valid']) or empty($externalVisitor['user_is_verified'])) { return $this->responseError(new XenForo_Phrase('bdapi_consumer_x_account_not_good_standing', array('provider' => $provider['name']))); } } $userModel = $this->_getUserModel(); $userExternalModel = $this->_getUserExternalModel(); $existingAssoc = $userExternalModel->getExternalAuthAssociation($userExternalModel->bdApiConsumer_getProviderCode($provider), $externalVisitor['user_id']); $autoRegistered = false; if (empty($existingAssoc)) { $existingAssoc = $this->_bdApiConsumer_autoRegister($provider, $externalToken, $externalVisitor); if (!empty($existingAssoc)) { $autoRegistered = true; } } if ($existingAssoc && $userModel->getUserById($existingAssoc['user_id'])) { $redirect = XenForo_Application::get('session')->get(self::SESSION_KEY_REDIRECT); XenForo_Application::get('session')->changeUserId($existingAssoc['user_id']); XenForo_Visitor::setup($existingAssoc['user_id']); XenForo_Application::get('session')->remove(self::SESSION_KEY_REDIRECT); if (empty($redirect)) { $redirect = $this->getDynamicRedirect(false, false); } if (!$autoRegistered) { $userExternalModel->bdApiConsumer_updateExternalAuthAssociation($provider, $externalVisitor['user_id'], $existingAssoc['user_id'], $externalVisitor + array('token' => $externalToken)); } return $this->responseRedirect(XenForo_ControllerResponse_Redirect::SUCCESS, $redirect); } $existingUser = false; $emailMatch = false; if (XenForo_Visitor::getUserId()) { $existingUser = XenForo_Visitor::getInstance(); } elseif ($assocUserId) { $existingUser = $userModel->getUserById($assocUserId); } if (!$existingUser) { $existingUser = $userModel->getUserByEmail($externalVisitor['user_email']); $emailMatch = true; } if ($existingUser) { // must associate: matching user return $this->responseView('bdApiConsumer_ViewPublic_Register_External', 'bdapi_consumer_register', array('associateOnly' => true, 'provider' => $provider, 'externalToken' => $externalToken, 'externalVisitor' => $externalVisitor, 'existingUser' => $existingUser, 'emailMatch' => $emailMatch, 'redirect' => $redirect)); } if (bdApiConsumer_Option::get('bypassRegistrationActive')) { // do not check for registration active option } else { $this->_assertRegistrationActive(); } $externalVisitor['username'] = bdApiConsumer_Helper_AutoRegister::suggestUserName($externalVisitor['username'], $userModel); return $this->responseView('bdApiConsumer_ViewPublic_Register_External', 'bdapi_consumer_register', array('provider' => $provider, 'externalToken' => $externalToken, 'externalVisitor' => $externalVisitor, 'redirect' => $redirect, 'customFields' => $this->_getFieldModel()->prepareUserFields($this->_getFieldModel()->getUserFields(array('registration' => true)), true), 'timeZones' => XenForo_Helper_TimeZone::getTimeZones(), 'tosUrl' => XenForo_Dependencies_Public::getTosUrl()), $this->_getRegistrationContainerParams()); }