Please add support for external Database authentication

Penguinexpert1

Active member
Hi there,

I have an external PHP site that I would like to integrate with XenForo.

It would be nice if XenForo could use the database that I already have (passwords stored with bcrypt), by being told which fields to lookup for certain functions.

For example, IPB (Invision) offers this functionality already, as seen below:
1.thumb.png.485edd9d3e6cd61e397e0149e57422d6.png

2.thumb.png.eb16e239b7444a9c303644deb17a9c2b.png


By having this type of ability in the core, then XenForo can be so much more customisable and developer-friendly, rather than having to rely on the REST API.

This was the one of the main features when I was choosing between IPB and XF, finally settled on XF, but would LOVE to see this functionality, as it is crucial for a good user experience.

Please, please add this functionality into the core!
 
Upvote 11

Penguinexpert1

Active member
Sadly I'm now moving to coding my own forums for my community, as this is a necessary feature that isn't in XenForo. Sadly that's $140 + add-ons that are down the drain just for the lack of one necessary feature.

Hopefully, one day this will be added and I can come back to XenForo.
 

Lee

Well-known member
Sadly I'm now moving to coding my own forums for my community, as this is a necessary feature that isn't in XenForo. Sadly that's $140 + add-ons that are down the drain just for the lack of one necessary feature.

Hopefully, one day this will be added and I can come back to XenForo.
Wouldn't it make more sense to code the missing feature not an entire forum suite?
 

Forsaken

Well-known member
Wouldn't it make more sense to code the missing feature not an entire forum suite?
Depends on the site and scope of the project; I know for my specific site it is going to eventually make more sense to build out our own platform so that things tie together seamlessly, rather than trying to hold everything together with used bubblegum and tooth picks. That was actually the plan late 2019 to early 2020, but then the developer who was on staff switched jobs and his wife decided it was a good time to have a pandemic baby, so all his time is now gone.
 

ChrisPine

New member
Kinda sad that something this easy for the obviously very busy people of XF can be overlooked. I'm unsure why they didn't just do it anyway. Thirty Bees and other companies are just taking their code and doing the work. It is why people won't pay for addons... You think my clients want to have 2 different login systems...lmao.. but Forsaken... I'm working on the addon and when we are done with SSO and removing the lazy work of REST... I'll PM you directly. Not giving this to XF because they don't deserve it. They want people to drive straight into the loving arms of their "Private Devs" who take money. Like bruh...just add Google Ads to your site if you need revenue....lol you get enough unique site visits.

Also no need for XFers to champion their cause.. no one cares. :)
 

ChrisPine

New member
class User extends Authenticatable { use Notifiable; protected $fillable = ['username', 'email', 'password', 'user_state']; protected $connection = 'forum'; protected $table = 'xf_user'; protected $primaryKey = 'user_id'; public $timestamps = false; public function getAuthPassword(){ $password = Password::where('user_id', '=', $this->user_id)->select('data')->first(); return unserialize($password->data)['hash']; } }

Working off of implementing this code into the Module. Call to either a single DB or multiple columns if you're running Prestashop, Abantecart, or any other 3rd party... removing the primitive encrypting passwords.. and authenticating users by passwd, usrname, and 2FA.

It worked for a second on 1.6 but when I applied it to 2.x no go. Rechecking.....

REPLY
🤷‍♂️ that was kind of my reaction.

I went south when 2 years passed without any visible push from developers to create a staple Addon in the forum software community. Wait oh they were busy making new themes! Goody! They were building addons to attach files to the homepage! Nice! Like, lmao. Stop.

Oh and for those that are wondering.. specifically XF... no I did not purchase XF. I code for hire and I'm currently stuck under the insistence of using your software until I can get this working again or convince him to move forward with IPB. Was pretty close. I wonder.. how much a dev would sell this addon for though.... $149??



<?php
class appXenForo {

//Singleton Storage
private static $bInitialized = false;

/**
* Initialise XenForo Functions
*/
function __construct() {

}

/*
* Initialise the XenForom Controllers:
*/

public static function init() {
define('XF_ROOT', $_SERVER['DOCUMENT_ROOT'] . '/testsite/forum'); // set this always to xenforo root folder!
define('TIMENOW', time());
define('SESSION_BYPASS', false);
require_once(XF_ROOT . '/library/XenForo/Autoloader.php');
XenForo_Autoloader::getInstance()->setupAutoloader(XF_ROOT . '/library');
XenForo_Application::initialize(XF_ROOT . '/library', XF_ROOT);
XenForo_Application::set('page_start_time', TIMENOW);
XenForo_Application::disablePhpErrorHandler();
XenForo_Session::startPublicSession();
error_reporting(E_ALL & ~E_NOTICE);
}

/*
* Set the user password.
*/

public static function setPassword($iID, $sPassword) {

$db = XenForo_Application::get('db');

$sQuery = "UPDATE xf_user_authenticate SET data = BINARY
CONCAT(CONCAT(CONCAT('a:3:{s:4:\"hash\";s:40:\"',
SHA1(CONCAT(SHA1('$sPassword'), SHA1('salt')))),
CONCAT('\";s:4:\"salt\";s:40:\"', SHA1('salt'))),
'\";s:8:\"hashFunc\";s:4:\"sha1\";}'),scheme_class = 'XenForo_Authentication_Core'
WHERE user_id = $iID;";

$db->fetchRow($sQuery);
}


/*
* Update email of xf_user
*/
public static function updateEmailUser($iId,$sEmail){

$db = XenForo_Application::get('db');

$sQuery = "UPDATE xf_user SET email = '$sEmail' WHERE user_id = $iId;";

$db->fetchRow($sQuery);

}


/*
* Get an array of the latest posts:
*/

public static function getLatestPosts($iMax) {
$sQuery = "SELECT thread.last_post_id as post_id,
thread.last_post_user_id as user_id,
thread.last_post_username as username ,
thread.discussion_state,
thread.last_post_date,
thread.title as threadtitle,
thread.thread_id as thread_id,
forum.title as node_title, forum.node_id as node_id
FROM xf_thread as thread
LEFT JOIN xf_node as forum ON (forum.node_id = thread.node_id)
ORDER BY thread.last_post_date DESC
LIMIT $iMax";

//Get the rows:
$aLatest = query($sQuery);

// Loop over each post, get the message
foreach ($aLatest as &$cPost) {
//Get the message:
$aRow = query("SELECT * FROM xf_post WHERE post_id = ? LIMIT 1", array($cPost['post_id']));
$cPost['message'] = self::stripBBCode($aRow['message']);
}

return $aLatest;
}

/*
* Get a filtered string URL for the thread:
*/

public static function getThreadURL($sThreadTitle, $iThreadID) {
$sThreadURL = strtolower(str_replace(" ", "-", $sThreadTitle));
$sThreadURL = preg_replace("/[^A-Za-z0-9-]/", '', $sThreadURL);
return "forum/index.php?threads/{$sThreadURL}.{$iThreadID}";
}

/*
* Get a filtered string URL for a node / forum/.
*/

public static function getNodeURL($sNodeTitle, $iNodeID) {
$sForumURL = strtolower(str_replace(" ", "-", $sNodeTitle));
$sForumURL = preg_replace("/[^A-Za-z0-9-]/", '', $sForumURL);
return "forum/index.php?forums/{$sNodeURL}.{$cPost['node_id']}/";
}

/*
* Strip out BB code from xfPosts
*/

public static function stripBBCode($sMessage) {
return strip_tags(str_replace(array('[', ']'), array('<', '>'), $sMessage));
}

/*
* Create a XenForo User:
*/

public static function createUser($sUsername, $sEmail, $sPassword, array $aAdditionalData = array()) {

//Create the username from the person's name:
$sUsername = str_replace(' ', "_", $sUsername);

//Set User Data
$cWriter = XenForo_DataWriter::create('XenForo_DataWriter_User');
$cWriter->set('username', $sUsername);
$cWriter->set('email', $sEmail);
$cWriter->setPassword($sPassword);
$cWriter->set('user_group_id', XenForo_Model_User::$defaultRegisteredGroupId);
$cWriter->set('user_state', 'valid');

//echo"<pre>";print_r($cWriter);

foreach ($aAdditionalData AS $data => $key) {
$cWriter->set($data, $key);
}
$cWriter->save();
$cUser = $cWriter->getMergedData();

//Login new user: Log the ip of the user registering
XenForo_Model_Ip::log($cUser['user_id'], 'user', $cUser['user_id'], 'register');
//Set the user back to the browser session
XenForo_Application::get('session')->changeUserId($cUser['user_id']);
XenForo_Visitor::setup($cUser['user_id']);

return $cUser['user_id'];
}

/*
* Get the current user:
*/

public static function getCurrentUser() {

XenForo_Session::startPublicSession();
$cVisitor = XenForo_Visitor::getInstance();
if ($cVisitor->getUserId()) {
$dbUserModel = XenForo_Model::create('XenForo_Model_User');
$cUserInfo = $dbUserModel->getFullUserById($cVisitor->getUserId());
}
return $cUserInfo;
}

/*
* Get the current user:
*/

public static function getUserByEmail($sEmail) {
$dbUserModel = XenForo_Model::create('XenForo_Model_User');
$cUser = $dbUserModel->getUserByEmail($sEmail, array('join' => XenForo_Model_User::FETCH_USER_PROFILE + XenForo_Model_User::FETCH_LAST_ACTIVITY));
return $cUser;
}

/*
* Set the user state: from email_confirm to valid.
*/

public static function setUserState($iXFID, $sState) {
//'valid'
//'email_confirm'
//query("UPDATE xf_user SET user_state = ? WHERE user_id = ? LIMIT 1", array($sState, $iXFID));
}

/*
* Login a XenForo User // Set the cookie.
*/

public static function login($sEmail, $sPassword, $bRemember = true) {

//Get this class; delete existing login information
error_reporting(E_ALL);
restore_error_handler();
restore_exception_handler();

$dbLoginModel = XenForo_Model::create('XenForo_Model_Login');
$dbUserModel = XenForo_Model::create('XenForo_Model_User');
$sError = "";

$iUserID = $dbUserModel->validateAuthentication($sEmail, $sPassword, $sError);
if (!$iUserID) {
$dbLoginModel->logLoginAttempt($sEmail);
return $sError;
}

$dbLoginModel->clearLoginAttempts($sEmail);

if ($bRemember) {
$dbUserModel->setUserRememberCookie($iUserID);
}

XenForo_Model_Ip::log($iUserID, 'user', $iUserID, 'login');

$dbUserModel->deleteSessionActivity(0, $_SERVER['REMOTE_ADDR']);

$cSession = XenForo_Application::get('session');
$cSession->changeUserId($iUserID);
XenForo_Visitor::setup($iUserID);

return $iUserID;
}

/*
* Set this user ID as logged in.
*/

public static function setLogin($iUserID) {
$dbUserModel = XenForo_Model::create('XenForo_Model_User');
$dbUserModel->setUserRememberCookie($iUserID);
XenForo_Model_Ip::log($iUserID, 'user', $iUserID, 'login');
$dbUserModel->deleteSessionActivity(0, $_SERVER['REMOTE_ADDR']);
$cSession = XenForo_Application::get('session');
$cSession->changeUserId($iUserID);
XenForo_Visitor::setup($iUserID);
}

/*
* Check if this user name is in use, return true for already exists.
*/

public static function bUsernameInUse($sUsername) {

$db = XenForo_Application::get('db');

$cUser = $db->fetchRow("SELECT * FROM xf_user WHERE username = '$sUsername' LIMIT 1");

if (is_numeric($cUser['user_id'])) {
return true;
} else {
return false;
}
}

/*
* Get all the posts belonging to this user: with this XFID, and limit X posts:
*/

public static function getMyPosts($iXFID, $iLimit = 10) {
//Get the rows:
$aMyPosts = query("SELECT * FROM xf_post WHERE user_id = ? ORDER BY post_date DESC LIMIT ?", array($iXFID, $iLimit));
//$aMyPosts = appDB::arrayify($aMyPosts); //Check is array for the foreach.
// Loop over each post, get the thread information:
foreach ($aMyPosts as &$cPost) {
//Process the BB code out:
$cPost['message'] = self::stripBBCode($cPost['message']);
//Get the Thread Title:
$cPost['thread'] = query("SELECT * FROM xf_thread WHERE thread_id = ? LIMIT 1", array($cPost['thread_id']));
//Get Forum Info:
$cPost['forum'] = query("SELECT * FROM xf_forum WHERE node_id = ? LIMIT 1", array($cPost['thread']['node_id']));
}
return $aMyPosts;
}

/*
* Delete the current session and log out.
*/

public static function logout() {
if (XenForo_Visitor::getInstance()->get('is_admin')) {
$adminSession = new XenForo_Session(array('admin' => true));
$adminSession->start();
if ($adminSession->get('user_id') == XenForo_Visitor::getUserId()) {
$adminSession->delete();
}
}
XenForo_Model::create('XenForo_Model_Session')->processLastActivityUpdateForLogOut(XenForo_Visitor::getUserId());
XenForo_Application::get('session')->delete();
XenForo_Helper_Cookie::deleteAllCookies(
array('session'), array('user' => array('httpOnly' => false))
);
XenForo_Visitor::setup(0);
return;
}

}
 
Last edited:
Top