Back to blog

How to integrate phpbb forum login

I have had to install phpbb forum on a website that already had a user table and I want to…

I have had to install phpbb forum on a website that already had a user table and I want to keep the users of my table as the only users of the web site. I want to give to my users the access to the phpbb functionalities.

I’ve searched for a ready-to-use component but it seems that it doesn’t exists. I’ve tried to watch the source of phpbb to understand if changing the whole code to match my table was a valid path to run, but it seems to be too complex, there are too many occurrence of the user table in the code. So I’ve tried to understand if mapping records could be a solution and I’ve found many people that walk this way. I’ve found a Php class that does some of the work mapping users but it wasn’t enough, so here is my 10 steps tutorial.

phpbb integration forum scheme

STEP 1: install phpbb forum (i’ve used version 3)
Read documentation of phpbb on how to install the forum, it’s quite easy, there is a good wizard. For the admin user choose a username that is an admin on your user table so the mapping will be correct.

STEP 2: download this phpbbintegration.class.php [download]
This class does a relevant job: it allows you to copy your users from your community into phpbb tables.
It also does the update password and something more:

<?
/*	
	PHPBB3 Integration class
	=================================================================================
	this class is based on the work of Jonathan Gibb, http://www.polr.co.uk
	and modified by Giulio Pons https://www.barattalo.it to handle also
	the login process.
	A complete tutorial can be found here: 
	
How to integrate phpbb forum login
* Functionality: * -------------- * Add a user to PHPBB3 * Change users password on PHPBB3 * Disable/ban user on PHPBB3 * Enable/un-ban user on PHPBB3 ================================================================================= */ // CONFIG // ====== define('ROOT_PATH', "../forum/"); // map this dir to your own installation of phpbb define('IN_PHPBB', true); if (!defined('IN_PHPBB') || !defined('ROOT_PATH')) exit(); $phpEx = "php"; $phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : ROOT_PATH . '/'; include($phpbb_root_path . 'common.' . $phpEx); $user->session_begin(); $auth->acl($user->data); $user->setup(); class Phpbb3Integration { var $table_prefix; var $connection; var $lang; var $default_timezone; var $user_dst; var $user_dateformat; var $user_colour; function Phpbb3Integration($table_prefix = 'phpbb_') { // CONFIG // ====== $this->lang = "it"; // language, I've tried "it" and "en" $this->default_timezone = "1.00"; // +1 hour $this->user_dst = 1; // use legal time $this->user_dateformat = "|d/m/Y|, G:i"; // date format $this->user_colour = "9E8DA7"; // user colour $this->table_prefix = $table_prefix; } function connect($server,$dbuser,$dbpass,$dbname) { $this->connection = mysql_connect ( $server, $dbuser, $dbpass ); if (!$this->connection) return false; if (!mysql_select_db ( $dbname, $this->connection )) return false; return true; } function addNewUser($username,$password,$email,$ip) { $sql = $this->createSqlToAddUserRow ( $username, $password, $email, $ip ); mysql_query ( $sql, $this->connection ); $id = mysql_insert_id ( $this->connection ); $sql = $this->createSqlToAddUserGroupRow ( $id ); mysql_query ( $sql, $this->connection ); } function changeUserPassword($username,$password) { $sql = $this->createSqlToUpdateUserPassword ( $username, $password ); mysql_query ( $sql, $this->connection ); } function disableUser($username) { // first get phpbb internal id for username $sql = "select user_id from " . $this->table_prefix . "users where username = '$username'"; $query = mysql_query ( $sql, $this->connection ); if (! $query) return false; $id = mysql_result ( $query, 0 ); // create ban row $banSql = "insert into " . $this->table_prefix . 'banlist (ban_userid, ban_start, ban_reason, ban_give_reason)'; $banSql .= "values ('$id','" . time () . "', 'External Integration','Banned by External Integration')"; mysql_query ( $banSql, $this->connection ); } function enableUser($username) { // first get phpbb internal id for username $sql = "select user_id from " . $this->table_prefix . "users where username = '$username'"; $query = mysql_query ( $sql, $this->connection ); if (! $query) return false; $id = mysql_result ( $query, 0 ); // delete ban row $deleteSql = "DELETE FROM " . $this->table_prefix . 'banlist where ban_userid = ' . $id; $query = mysql_query ( $deleteSql, $this->connection ); return ($query != false); } // Helper Methods // ============== /** * Generate salt for hash generation */ function _hash_gensalt_private($input,&$itoa64,$iteration_count_log2 = 6) { if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) $iteration_count_log2 = 8; $output = '$H ; $output .= $itoa64 [min ( $iteration_count_log2 + ((PHP_VERSION >= 5) ? 5 : 3), 30 )]; $output .= $this->_hash_encode64 ( $input, 6, $itoa64 ); return $output; } /** * Encode hash */ function _hash_encode64($input,$count,&$itoa64) { $output = ''; $i = 0; do { $value = ord ( $input [$i ++] ); $output .= $itoa64 [$value & 0x3f]; if ($i < $count) $value |= ord ( $input [$i] ) << 8; $output .= $itoa64 [($value >> 6) & 0x3f]; if ($i ++ >= $count) break; if ($i < $count) $value |= ord ( $input [$i] ) << 16; $output .= $itoa64 [($value >> 12) & 0x3f]; if ($i ++ >= $count) break; $output .= $itoa64 [($value >> 18) & 0x3f]; } while ( $i < $count ); return $output; } /** * The crypt function/replacement */ function _hash_crypt_private($password,$setting,&$itoa64) { $output = '*'; // Check for correct hash if (substr ( $setting, 0, 3 ) != '$H ) return $output; $count_log2 = strpos ( $itoa64, $setting [3] ); if ($count_log2 < 7 || $count_log2 > 30) return $output; $count = 1 << $count_log2; $salt = substr ( $setting, 4, 8 ); if (strlen ( $salt ) != 8) return $output; /** * We're kind of forced to use MD5 here since it's the only * cryptographic primitive available in all versions of PHP * currently in use. To implement our own low-level crypto * in PHP would result in much worse performance and * consequently in lower iteration counts and hashes that are * quicker to crack (by non-PHP code). */ if (PHP_VERSION >= 5) { $hash = md5 ( $salt . $password, true ); do { $hash = md5 ( $hash . $password, true ); } while ( -- $count ); } else { $hash = pack ( 'H*', md5 ( $salt . $password ) ); do { $hash = pack ( 'H*', md5 ( $hash . $password ) ); } while ( -- $count ); } $output = substr ( $setting, 0, 12 ); $output .= $this->_hash_encode64 ( $hash, 16, $itoa64 ); return $output; } function unique_id($extra = 'c') { static $dss_seeded = false; global $config; $val = $config ['rand_seed'] . microtime (); $val = md5 ( $val ); $config ['rand_seed'] = md5 ( $config ['rand_seed'] . $val . $extra ); $dss_seeded = true; return substr ( $val, 4, 16 ); } function phpbb_hash($password) { $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; $random_state = $this->unique_id (); $random = ''; $count = 6; if (($fh = @fopen ( '/dev/urandom', 'rb' ))) { $random = fread ( $fh, $count ); fclose ( $fh ); } if (strlen ( $random ) < $count) { $random = ''; for($i = 0; $i < $count; $i += 16) { $random_state = md5 ( $this->unique_id () . $random_state ); $random .= pack ( 'H*', md5 ( $random_state ) ); } $random = substr ( $random, 0, $count ); } $hash = $this->_hash_crypt_private ( $password, $this->_hash_gensalt_private ( $random, $itoa64 ), $itoa64 ); if (strlen ( $hash ) == 34) return $hash; return md5 ( $password ); } function createSqlToAddUserRow($username,$password,$email,$ip) { $sql = "INSERT INTO `" . $this->table_prefix . "users` ("; $sql .= "`user_id`, `user_type`, `group_id`, `user_permissions`, `user_perm_from`, `user_ip`, `user_regdate`, `username`, `username_clean`, `user_password`, `user_passchg`, `user_pass_convert`, `user_email`, `user_email_hash`, `user_birthday`, `user_lastvisit`, `user_lastmark`, `user_lastpost_time`, `user_lastpage`, `user_last_confirm_key`, `user_last_search`, `user_warnings`, `user_last_warning`, `user_login_attempts`, `user_inactive_reason`, `user_inactive_time`, `user_posts`, `user_lang`, `user_timezone`, `user_dst`, `user_dateformat`, `user_style`, `user_rank`, `user_colour`, `user_new_privmsg`, `user_unread_privmsg`, `user_last_privmsg`, `user_message_rules`, `user_full_folder`, `user_emailtime`, `user_topic_show_days`, `user_topic_sortby_type`, `user_topic_sortby_dir`, `user_post_show_days`, `user_post_sortby_type`, `user_post_sortby_dir`, `user_notify`, `user_notify_pm`, `user_notify_type`, `user_allow_pm`, `user_allow_viewonline`, `user_allow_viewemail`, `user_allow_massemail`, `user_options`, `user_avatar`, `user_avatar_type`, `user_avatar_width`, `user_avatar_height`, `user_sig`, `user_sig_bbcode_uid`, `user_sig_bbcode_bitfield`, `user_from`, `user_icq`, `user_aim`, `user_yim`, `user_msnm`, `user_jabber`, `user_website`, `user_occ`, `user_interests`, `user_actkey`, `user_newpasswd`, `user_form_salt`"; $sql .= ")"; $sql .= "VALUES ("; $sql .= "NULL, '0', '2', '00000000006xv1ssxs\ni1cjyo000000\nqlc4pi000000\nzik0zi000000', '0', '" . $ip . "', '" . time () . "', '$username', '$username',"; $sql .= "'" . $this->phpbb_hash ( $password ) . "', '" . time () . "', '0', '$email',"; $sql .= " '0', '', '" . time () . "', '" . time () . "', '" . time () . "', '', '',"; $sql .= "'0', '0', '0', '0', '0', '0', '0',"; $sql .= "'{$this->lang}', '{$this->default_timezone}', '{$this->user_dst}', '{$this->user_dateformat}', '1', '0',"; $sql .= "'{$this->user_colour}', '0', '0', '0', '0', '-3', '0', '0', 't', 'd', '0', 't', 'a', '0', '1', '0', '1', '1', '1',"; $sql .= "'1', '895', '', '0', '0', '0', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '1a99da7f3160cc5c'"; $sql .= ")"; return $sql; } function createSqlToAddUserGroupRow($phpbb_user_id) { $sql = "INSERT INTO `" . $this->table_prefix . "user_group` (`group_id`, `user_id`, `group_leader`, `user_pending`) VALUES ('2', '$phpbb_user_id', '0', '0')"; return $sql; } function createSqlToUpdateUserPassword($username,$newPassword) { $sql = "update `" . $this->table_prefix . "users` set user_password = '" . $this->phpbb_hash ( $newPassword ) . "' where username = '" . $username . "'"; return $sql; } } ?>

Note: there is a line of code at the beginning that you have to config, and there are a few lines inside the constructor, change them to match your phpbb3 installation.

STEP 3: handle conflicts
Since I’m using original phpbb files there are some possible conflicts to handle when you include the phpbbintegration.class.php, so, follow these rules in the pages that use phpbbintegration class:
– don’t use a class called “Session” since this is the name of the class that handles sessions in phpbb code.
– don’t use global variables with those names: $db, $user, $auth. Those variables are the main objects of the phpbb user system, so rename your variables.

STEP 4: modify your registration process to handle the creation of the users also on the phpbb tables
In my community I use an opt-in process so I’ve added the copy of the user after the opt-in process is completed:

// my includes... add the new class:
include("res/inc/PHPBB3Integration.class.php");

// ...my php that make the registered user valid
// such as the update to flag the email as valid
// after the opt-in process.

// ...
$userobj = getUserData($id); // user obj contains the data of the user in my community
$_SESSION['logged']=$userobj['id']; // login my user
// ...

// ----------------------------------------
// the new code to add: copy the new user into forum
$forum = new Phpbb3Integration();
$forum->connect ( WEBDOMAIN, DEFUSERNAME, DEFDBPWD, DEFDBNAME );
$forum->addNewUser ( $userobj['username'], $userobj['password'], $userobj['email'], getIP() );
// ----------------------------------------
// log in the user using the the phpbb auth object
$auth->login( $userobj['username'], $userobj['password'], true, 1, 0);

STEP 5: modify your login to login also on the forum

// my includes... add the new class:
include("res/inc/PHPBB3Integration.class.php");

$username = $_POST['user'];
$password = $_POST['pass'];

$userobj= execute_row("select * from myusers where status=1 and username='".addslashes($username)."' and password='".addslashes($password)."'");

if(is_array($userobj) && $row['id']>0) {
	$_SESSION['logged']=$userobj['id']; // login my user
	// login on phpbb forum
	$auth->login( $userobj['username'], $userobj['password'], true, 1, 0);
} else {
	die("login failed");
}

STEP 6: modify your logout process to logout also on the forum
Add the include of the class and add those lines to you logout:

// logout from phpbb
$user->session_kill();
$user->session_begin();

STEP 7: disable native registration in phpbb
Login in with the admin in the phpbb forum and disable the registration of new users, there is specific option to set in the administration control panel.

STEP 8: modify templates to remove phpbb unwanted features
You have to remove the blocks that print the login form from login_body.html file placed in the forum/styles/[skinname]/templates directory (remove also the reset password) and remove the block for login in login_forum.html. If you don’t want to remove the login forms you can modify them to post to your system and go back to the forum.
Remember that you also have to remove the block that show the commands to change email and password in ucp_profile_reg_details.html.

STEP 9: modify your change password process
You have to change the password also in the phpbb forum using the integration class changeUserPassword method.

The whole integration process can be quite unobtrusive if you don’t have code conflicts (step 3) and it’s good since we didn’t touch the phpbb code, but only its config files and its templates, so it could happen that this tutorial will works also after the future upgrades.

STEP 10: first porting
It could be necessary, if you have an already existing community, that you first have to make a script the copy all your active user to your phpbb forum. Just make a script that has the connection to the db, include the integration class, and the cycle through your user and for each record call the addNewUser function.

Canonical URL