Because of the interest this topic might have, I decided to write this entry in English, instead of my usual Dutch posts.
For a new website I’m currently writing in CakePHP, I needed to integrate a forum as well as a blog into it, so a single sign-on is enough for the user to post on all three systems. I’m still working on the blog part, but the forum part is already done and working. I decided to go with FluxBB, since I know that one best from the inside and I like the fact that it’s very lightweight.
Requirements:
- CakePHP 1.3.6
- FluxBB 1.4.2
It will most likely work on any version from the branches above (so Cake 1.3.x and FluxBB 1.4.x), but I have not tested this. If you happen to try this out on any other version(s), please post a comment if this works or not, it would help a lot of other people
For initial user authentication, I am using Cake’s Auth component. This will be the component that handles the authentication process, also on behalf of the FluxBB side.
User registration
The first thing we’ll want to do is to adjust the Users controller of our Cake app to also handle the registration for new users and verifying logins on Flux’s behalf. I’ll get into the registration side first.
When a new user is registered in our Cake app, we want to give this user an entry in the Flux user table as well. It’s pretty straight forward, since this is just a customized INSERT query into the Flux user table. This code comes from the register function in the Users controller, after adding the user to Cake’s tables.
// Also add a forum user with the same details $pun_config = array(); $now = time(); require_once('../webroot/forum/cache/cache_config.php'); $this->User->query(" INSERT INTO `fluxbb_users` ( `username`, `group_id`, `password`, `email`, `email_setting`, `timezone`, `dst`, `language`, `style`, `registered`, `registration_ip`, `last_visit` ) VALUES( '" . mysql_escape_string($this->data['User']['screen_name']) . "', " . $pun_config['o_default_user_group'] . ", '" . sha1($this->data['User']['password2']) . "', '" . mysql_escape_string($this->data['User']['email']) . "', " . $pun_config['o_default_email_setting'] . ", 0, 0, '" . $pun_config['o_default_lang'] . "', '" . $pun_config['o_default_style'] . "', " . $now . ", '" . $_SERVER['REMOTE_ADDR'] . "', " . $now . " )" );
I’ve added some line breaks for better readability. In my actual code the query is just on 2 lines (1 for INSERT INTO and one for VALUES). Now, let’s break it down a little bit, so you understand what this piece of code is doing. At first, I initiate the $pun_config array, to hold some of our FluxBB default settings as values. As you might know, FluxBB is branched off of PunBB, so in Flux’s code you’ll see a lot of Pun entries come back. It might be a bit confusing at first, but if you just read “Flux” where it says “Pun”, it’ll get familiar to you.
Secondly, the $now variable will hold the current timestamp, so we can insert when the user was created.
Up next, and very important, I require the cache_config.php. This file holds some of the values we need to insert the user with the actual default values set in our FluxBB install. You could just overwrite these default values with your own values, but I thought it was better to have Flux get the final say in what the default values should be, instead of me “forcing” them into the database. Forcing it might get funky results, especially if the default usergroup or something like that would change in the future. In my case, I had the forum installed under app/webroot/forum of my CakePHP app. Thus, from the controller I include ../webroot/forum/cache/cache_config.php, this path might differ in your case.
Finally and most important of them all, the actual query. I send a raw query to the fluxbb_users table using Cake’s query function. Since the fluxbb_users is not an actual part of my application, the save function does not meet my needs here, although it might be an even better idea to use something like User hasOne FluxBBUser in your Cake structure. But, at the time, I needed to get this up and running quickly, so I haven’t fully thought that out yet, perhaps in the future. Now, note that the following variables might differ in your case:
- $this->data['User']['screen_name'] – This represents the username that the user will have on the forum.
- $this->data['User']['password2'] – This represents a raw version of the password, the default ‘password’ will be hashed by Cake before you reach this point, so that would make it impossible to log the user in as the sha1 will be done on the already hashed password.
- $this->data['User']['email'] – This represents the user’s e-mail address (obviously)
So, be sure to adjust anything where necessary to make it all work.
This is pretty much everything you need to do to insert the user into the Flux database. Pretty easy, right?
Logging In
Now comes the tricky part. We need to “mimic” the FluxBB authentication method into our Cake application and make it all work with the Auth component. Apart from the Auth component, I also added the Cookie component to hold the Flux cookie. So that will give you the following list of components in the Users controller:
var $components = array('Auth', 'Cookie');
Next up, I also need some private variables that will be set and read throughout the controller. Just under the components line, add these:
private $flux_cookie_name = ''; private $flux_cookie_seed = ''; private $flux_cookie_hash = '';
Now that’s all set, we’re getting to the part where we’ll actually start filling the variables and setting some of the cookie’s properties by reading Flux’s config file. In your Users controller, add (or adjust) the beforeFilter function to pass this information to the cookie Controller.
function beforeFilter() { // FluxBB: Generate cookie and it's hash require_once('../webroot/forum/config.php'); $this->flux_cookie_name = $cookie_name; $this->flux_cookie_seed = $cookie_seed; $this->flux_cookie_hash = sha1($this->data['User']['password']); // Set Cookie component variables $this->Cookie->time = 1209600; $this->Cookie->domain = $cookie_domain; $this->Cookie->path = $cookie_path; $this->Cookie->secure = $cookie_secure; $this->Cookie->key = null; }
Breaking this down is quite simple. We require the FluxBB config file (again, in my case the forum is installed under app/webroot/forum, the require path might differ in your case) and set some of it’s variables. First, we set the name, seed and hash of the cookie. Then we pass some variables to Cake’s Cookie component.
Now that everything is prepared, we get to the actual login function. It should look something like this:
function login() { // If user is already logged in, redirect home if(empty($this->data) && $this->Session->check('Auth.User.id')) { $this->redirect('/'); return false; } // Parse login if((!empty($this->data)) && $this->Auth->user()){ $this->User->id = $this->Auth->user('id'); // FluxBB: Create cookie so we're logged in on the forums as well // Remove this users guest entry from the online list $this->User->query("DELETE FROM `fluxbb_online` WHERE ident='" . $_SERVER['REMOTE_ADDR'] . "'"); $flux_uid = $this->User->find('first', array( 'fields' => 'FluxUser.id', 'joins' => array( array( 'type' => 'INNER', 'table' => 'fluxbb_users', 'alias' => 'FluxUser', 'conditions' => 'FluxUser.email = User.email' ) ), 'conditions' => array( 'User.id' => $this->Auth->user('id') ) )); $this->Cookie->write($this->flux_cookie_name, serialize(array($flux_uid['FluxUser']['id'], md5($this->flux_cookie_seed.$this->flux_cookie_hash), time() + 1209600)), false); // Do auth magic and redirect $this->redirect($this->Auth->redirect()); } }
Let’s break this down some more. At first, I check if the user is already logged in. If so, I don’t care to continue any further and redirect the user back to the application’s root.
If the user is not yet logged in, let’s check if any data was submitted to the controller’s login function and if the authentication on Cake’s side of things was OK. If that’s the case, then we’re getting to the Flux side of things. At first, let’s remove the “Guest” (IP) entry from the fluxbb_online table, so the user is not counted as “guest” anymore. FluxBB does this same thing in it’s login.php.
Next, I want to fetch the FluxBB user id for this user. This is where the fun starts, since we’re now combining our CakePHP user table with FluxBB’s. The fetch itself is pretty simple, I just need the ‘id’ field from the fluxbb_users table. But it’s the join condition that requires some attention. In my case, people login with their e-mail address on the CakePHP Auth component. This might very well be a ‘regular’ username in your case, which would require a different join condition like FluxUser.username = User.username. You might need to play around a bit with your database models to get the proper join, but the code should look similar.
Finally, and most importantly we need to set the actual cookie. With all variables now in place, we can get this done with the following call:
$this->Cookie->write( $this->flux_cookie_name, serialize( array( $flux_uid['FluxUser']['id'], md5($this->flux_cookie_seed.$this->flux_cookie_hash), time() + 1209600 ) ), false );
I’ve added some linebreaks and tabs for readability. This whole block of code is actually on 1 line in my code. Now, what we do here is pretty much mimic the FluxBB authentication method. The cookie value consists of a serialized string, build up from the user id, a md5 hash of the cookie seed and cookie hash (which is in turn a sha1 hash of the user’s password) and the expiration time. To make sure that Cake does not hash the cookie data (otherwise Flux couldn’t read it), we pass a 3rd parameter of false to the Cookie component’s write function.
FluxBB modification
Now, you might think that we’re all done. Registrations are handled and a cookie is created upon login. Although, we need to make a minor adjust on the Flux side as well. Cake’s cookie component stores it’s “cookies” as keys in a “mother cookie” called CakeCookie (by default). Thus, our FluxBB authentication data is stored as $_COOKIE['CakeCookie'][$cookie_name].
At first I though I might just modify the Cookie component’s write function, but since that would pretty much require a complete rewrite of the Cookie component (read/write would all be different), I decided to go the easy way and just adjust the way that Flux checks for the cookie. This requires a modification in the include/functions.php file of the FluxBB installation.
This modification is rather simple, just do a search and replace like this:
$_COOKIE => $_COOKIE['CakeCookie']
This should be 8 changes throughout the file. Finally, you will probably want to “disable” Flux’s register/login functions, so Cake is leading in this. Easiest way to do this is to comment out the entries for this in the generate_navlinks function in the same functions file (should be 4 lines). I also disabled new user registrations in the Flux admin, so if people were to go directly to register.php, they can not continue. I didn’t bother to redirect the login.php, since my audience was a non-technical one, so I don’t figure they would manually go to login.php. And even if they would, it wouldn’t hurt anyone.
All done
After doing this, you’re finally done! Cake and Flux should now be fully integrated to one another, while still maintaining their own user database. Took me a whole night to get this thing figured out, hope it helps other people that are on the same quest to get it done faster
If you have any questions, please feel free to post them in the coments.

Hi Jan,
Thanks for writing that up. It helped me a lot… Not that I was using cakePHP…
I did this using Yii
Cheers
Tom
Hi Tom,
Good to hear that this article helped you to integrate Flux into your Yii site
The idea should be similar, but with different syntax.