User Authentication with Codeigniter 1.7 using Facebook Connect

Exclusive offer: get 50% off this eBook here
CodeIgniter 1.7 Professional Development

CodeIgniter 1.7 Professional Development — Save 50%

Become a CodeIgniter expert with professional tools, techniques and extended libraries

$23.99    $12.00
by Adam Griffiths | May 2010 | Open Source PHP Web Development

In a previous article we covered User Authentication with Codeigniter 1.7 using Twitter oAuth. In this article by Adam Griffiths, author of CodeIgniter 1.7 Professional Development, we will continue our discussion on how we can utilize third-party authentication methods by using Facebook Connect.

Facebook Connect is just like Twitter oAuth, but for Facebook accounts. It doesn't use the oAuth protocol, so its workings might seem slightly different to developers. To users, however, the difference is marginal. Just like in Twitter oAuth, users do not need to enter any of their account credentials on your website or application—it is all handled by Facebook.

(Read more interesting articles on CodeIgniter 1.7 Professional Development here.)

Registering a Facebook application

You need to register a new Facebook Application so that you can get an API key and an Application Secret Key. Head on over to www.facebook.com/developers/ and click on the Set up New Application button in the upper right–hand corner.

This process is very similar to setting up a new Twitter application which we covered in the previous article, so I won't bore you with all of the details.

Once you've done that, you should have your API key and Application Secret Key. These two things will enable Facebook to recognize your application.

Download the Client library

When you are on your applications page showing all your applications' information, scroll down the page to see a link to download the Client Library. Once you've downloaded it, simply untar it.

There are two folders inside the facebook-platform folder, footprints and php. We are only going to be using the php folder. Open up the php folder; there are two files here that we don't need, facebook_desktop.php and facebook_mobile.php—you can delete them.

Finally, we can copy this folder into our application. Place it in the system/application/libraries folder, and then rename the folder to facebook. This helps us to keep our code tidy and properly sorted.

Our CodeIgniter Wrapper

Before we start coding, we need to know what we need to code in order to make the Facebook Client Library work with our CodeIgniter installation.

Our Wrapper library needs to instantiate the Facebook class with our API Key and Secret Application Key. We'll also want it to create a session for the user when they are logged in. If a session is found but the user is not authenticated, we will need to destroy the session.

You should create a new file in the system/application/libraries/ folder, called Facebook_connect.php. This is where the Library code given next should be placed.

Base class

The Base Class for our Facebook Connect Wrapper Library is very simple:

<?php

require_once(APPPATH . 'libraries/facebook/facebook.php');

class Facebook_connect
{
var $CI;
var $connection;

var $api_key;
var $secret_key;
var $user;
var $user_id;
var $client;
}

?>

The first thing that our Library needs to do is to load the Facebook library—the one we downloaded from facebook.com. We build the path for this by using APPPATH, a constant defined by CodeIgniter to be the path of the application folder.

Then, in our Class we have a set of variables. The $CI variable is the variable in which we will store the CodeIgniter super object; this allows us to load CodeIgniter resources (libraries, models, views, and so on) in our library. We'll only be using this to load and use the CodeIgniter Session library, however.

The $connection variable will contain the instance of the Facebook class. This will allow us to grab any necessary user data and perform any operations that we like, such as updating a user's status or sending a message to one of their friends.

The next few variables are pretty self-explanatory—they will hold our API Key and Secret Key.

The $user variable will be used to store all of the information about our user, including general details about the user such as their profile URL and their name. The $user_id variable will be used to store the user ID of our user.

Finally, the $client variable is used to store general information about our connection to Facebook, including the username of the user currently using the connection, amongst other things such as server addresses to query for things like photos.

Class constructor

Our class constructor has to do a few things in order to allow us to authenticate our users using Facebook Connect. Here's the code:

function Facebook_connect($data)
{

$this->CI =& get_instance();

$this->CI->load->library('session');

$this->api_key = $data['api_key'];
$this->secret_key = $data['secret_key'];

$this->connection =
new Facebook($this->api_key, $this->secret_key);
$this->client = $this->connection->api_client;
$this->user_id = $this->connection->get_loggedin_user();

$this->_session();
}

The first line in our function should be new to everyone reading this article. The function get_instance() allows us to assign the CodeIgniter super object by reference to a local variable. This allows us to use all of CodeIgniter's syntax for loading libraries, and so on; but instead of using $this->load we would use $this->CI->load. But of course it doesn't just allow us to use the Loader—it allows us to use any CodeIgniter resource, as we normally would inside a Controller or a Model. The next line of code gives us a brilliant example of this: we're loading the session library using the variable $this->CI rather than the usual $this.

The next two lines simply set the values of the API key and Secret Application Key into a class variable so that we can reference it throughout the whole class. The $data array is passed into the constructor when we load the library in our Controller. More on that when we get there.

Next up, we create a new instance of the Facebook Class (this is contained within the Facebook library that we include before our own class code) and we pass the API Key and Secret Application Key through to the class instance. This is all assigned to the class variable $this->connection, so that we can easily refer to it anywhere in the class.

The next two lines are specific parts of the overall Facebook instance. All of the client details and the data that helps us when using the connection are stored in a class variable, in order to make it more accessible. We store the client details in the variable $this->client. The next line of code stores all of the details about the user that were provided to us by the Facebook class. We store this in a class variable for the same reason as storing the client data: it makes it easier to get to. We store this data in $this->user_id.

The next line of code calls upon a function inside our class. The underscore at the beginning tells CodeIgniter that we only want to be able to use this function inside this class; so you couldn't use it in a Controller, for example. I'll go over this function shortly.

_session();

This function manages the user's CodeIgniter session. Take a look at the following code:

function _session()
{
$user = $this->CI->session->userdata('facebook_user');

if($user === FALSE && $this->user_id !== NULL)
{
$profile_data = array('uid','first_name', 'last_name',
'name', 'locale', 'pic_square', 'profile_url');
$info = $this->connection->api_client->
users_getInfo($this->user_id, $profile_data);

$user = $info[0];

$this->CI->session->set_userdata('facebook_user', $user);
}
elseif($user !== FALSE && $this->user_id === NULL)
{
$this->CI->session->sess_destroy();
}
if($user !== FALSE)
{
$this->user = $user;
}
}

This function initially creates a variable and sets its value to that of the session data from the CodeIgniter session library.

Then we go through a check to see if the session is empty and the $this->user_id variable is false. This means that the user has not yet logged in using Facebook Connect. So we create an array of the data that we want to get back from the Facebook class, and then use the function users_getInfo() provided by the class to get the information in the array that we created. Then we store this data into the $user variable and create a new session for the user.

The next check that we do is that if the $user variable is not empty, but the $this->user_id variable is empty, then the user is not authenticated on Facebook's side so we should destroy the session. We do this by using a function built in to the Session Library sess_destroy();

Finally, we check to see if the $user variable is not equal to FALSE. If it passes this check, we set the $this->user class variable to that of the local $user variable.

CodeIgniter 1.7 Professional Development Become a CodeIgniter expert with professional tools, techniques and extended libraries
Published: April 2010
eBook Price: $23.99
Book Price: $39.99
See more
Select your format and quantity:

(Read more interesting articles on CodeIgniter 1.7 Professional Development here.)

Final library code

Here is the full library code in context:

<?php

require_once(APPPATH . 'libraries/facebook/facebook.php');

class Facebook_connect
{
var $CI;
var $connection;

var $api_key;
var $secret_key;
var $user;
var $user_id;
var $client;

function Facebook_connect($data)
{

$this->CI =& get_instance();

$this->CI->load->library('session');

$this->api_key = $data['api_key'];
$this->secret_key = $data['secret_key'];

$this->connection =
new Facebook($this->api_key, $this->secret_key);
$this->client = $this->connection->api_client;
$this->user_id = $this->connection->get_loggedin_user();

$this->_session();
}

function _session()
{
$user = $this->CI->session->userdata('facebook_user');

if($user === FALSE && $this->user_id !== NULL)
{
$profile_data = array('uid','first_name', 'last_name',
'name', 'locale', 'pic_square', 'profile_url');
$info = $this->connection->api_client->
users_getInfo($this->user_id, $profile_data);

$user = $info[0];

$this->CI->session->set_userdata('facebook_user', $user);
}
elseif($user !== FALSE && $this->user_id === NULL)
{
$this->CI->session->sess_destroy();
}
if($user !== FALSE)
{
$this->user = $user;
}
}
}
?>

The Controller

The Controller is where all of our logic will go. The Controller that we use for our Facebook authentication will need to call upon the Facebook Connect Wrapper, set some local variables for some user information, and load a view file. The view file will contain special HTML elements to show Facebook information. These tags are known as Facebook Markup Language (FBML). We'll go over FBML briefly after this section.

<?php

class Facebooker extends Controller
{

function Facebooker()
{
parent::Controller();
$this->load->helper('url');
}

function index()
{
$data['api_key'] = "";
$data['secret_key'] = "";

$this->load->library('facebook_connect', $data);

$data['user'] = $this->facebook_connect->user;
$data['user_id'] = $this->facebook_connect->user_id;

$this->load->view('facebook', $data);
}
}
?>

As you can see, the Controller is fairly short and isn't as complex a way of authenticating users as Twitter oAuth (generating keys, and so on). I have named the Controller "Facebooker" because the class name "Facebook" has already been used for the core Facebook Client. If I had called the Controller Facebook there would be no output to the browser after a PHP failure. You should copy this code and save it in the system/application/controllers/ folder as Facebooker.php.

In the class constructor, we load the URL Helper. We use the URL Helper in the view file to tell Facebook the location of our application.

The first thing that we do in the index function is to declare two array keys: one for our API Key and another for the Secret Application Key. You should set these to the keys that you received from Facebook when you created a new application. We subsequently load the Facebook Connect Wrapper library, and pass the $data array containing our API key and Secret Application Key to it.

The next two lines add to our $data array, this time adding the user and user ID information. On the final line we load the view file and pass the $data array to it.

The View file

The View file is very important to us and needs some explaining. As you would expect from a Facebook Connect application, the logo will be placed on the web page. A pop-up box will appear when you click on it, allowing you to log in to Facebook and allow access to the application. To do this however, you need to know FBML. FBML is a superset of HTML and adds on to HTML's features, basically letting you easily add Facebook specific details. The example application is immensely simple, but it gives you a quick look at FBML, giving you an idea of what it can do and how it does it.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.
facebook.com/2008/fbml">
<head>
<title>Facebook Connect</title>
</head>
<body>
<script src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="http://static.ak.connect.facebook.com/js/api_lib/v0.4/
FeatureLoader.js.php" type="text/javascript"></script>
<?php if ( !$user_id ): ?>
<fb:login-button onlogin="window.location='<?=current_url()?>'">
</fb:login-button>
<?php else: ?>
<p><img class="profile_square" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="<?=$user['pic_square']?>" />
Hi <?=$user['first_name']?>!</p>
<p><a href="#" onclick="FB.Connect.logout(function()
{ window.location='<?=current_url()?>' });
return false;" >(Logout)</a></p>

<p>You are now logged in!!</p>
<?php endif; ?>
<script type="text/javascript">
FB.init("<?php echo $api_key; ?>", "/xd_receiver.htm");
</script>
</body>
</html>

As you can see, this is just a normal HTML document. We start off with a DOCTYPE declaration, open our html and head tags, set a page title and open our body tag. After this, though, we're in FBML territory.

The first thing that I have done is load in a JavaScript file so we can make use of all the Facebook Connect objects. Yes, I should do this in the <head> as opposed to after the <body> tag, but I've put it here to group all of the Facebook-specific stuff together.

In the following snippet of code, all I want to go through is the part that shows the Facebook Connect login button if a user is not logged in.

<?php if ( !$user_id ): ?>
<fb:login-button
onlogin="window.location='<?=current_url()?>'">
</fb:login-button>

The first line is just a simple PHP if statement. If the variable $user_id is not set, we show the login button. Let's take a closer look at the code behind adding the login button.

Firstly you should notice that the tag we are using, it's an <fb> tag. You should also notice that there is a colon in the tag, followed by a string to describe the object that we want to place on the web page—in this case it is the login-button. Then we set an attribute onlogin, which sets the redirect page to the one we are currently on; once a user is authenticated they'll still be on the same page. The current_url() function is part of the URL Helper that we loaded in the Controller constructor. Finally, we close the login button tag </fb:login-button>.

There isn't much to digest here, considering the operations behind this single button. All you need to take away from this section are the following points:

  • Facebook tags begin with <fb preceded by a colon and a string describing what you are adding to the page
  • Tags end the same as any HTML tag. The ending tags open with a </ instead of a <
  • Tags can have attributes

The next part of the code determines what happens when a user is logged in. Obviously we don't want to show a logged in user the login button! Instead, we will display their profile picture, print the text "Hi!" followed by their first name, and then show a logout link.

<?php else: ?>
<p><img class="profile_square" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="<?=$user['pic_square']?>" />
Hi <?=$user['first_name']?>!<p>
<p><a href="#" onclick="FB.Connect.logout(function()
{ window.location='<?=current_url()?>' });
return false;" >(Logout)</a></p>

<p>You are now logged in!!</p>
<?php endif; ?>

To begin with, we are simply following our initial if statement with an else. (Note that we are using shorthand PHP.) Next, we use an image tag to show the users profile picture. We add in the welcoming text and echo out the user's first name. Then we show the user a logout link.

The logout link uses the JavaScript onclick event to call a function (contained within the JS file that we loaded from Facebook), which logs the user out. Just like when showing the login button, we also send along the window.location as the current URL, so that the user will be sent back to this page after logging out. We also show the user a short message telling them they are now logged in.

The final part to the view file is simply including a JavaScript file. Notice that we are sending the string /xd_receiver.htm as a parameter. This is a file that we need to add to our CodeIgniter application so that we can make use of the JavaScript Library provided by Facebook.

<script type="text/javascript">
FB.init("<?php echo $api_key; ?>", "/xd_receiver.htm");
</script>

The file xd_receiver.html is a Cross Domain Communication Channel that allows us to us the JavaScript Library that Facebook has provided for us. The file should be placed at the root of our application—in the same folder as CodeIgniter's index.php file—so that it can be easily accessed. The file should contain the following code:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Cross-Domain Receiver Page</title>
</head>
<body>
<script
src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="http://static.ak.facebook.com/js/api_lib/v0.4/XdCommReceiver.js"
type="text/javascript">
</script>
</body>
</html>

The only difference between the previous code and the code that Facebook provides directly is the differing doctypes. I have used an HTML5 doctype, whereas Facebook uses an XHTML 1.0 Strict doctype in the example shown on their developer wiki.

Now that you have added this file, you can go ahead and login with Facebook Connect!

Summary

There you have it—user authentication using Twitter oAuth and Facebook Connect. There are many similarities in how these systems work, but for us developers they both work slightly differently; Twitter makes us jump through hoops, and Facebook handles it all for us.


If you have read this article you may be interested to view:


CodeIgniter 1.7 Professional Development Become a CodeIgniter expert with professional tools, techniques and extended libraries
Published: April 2010
eBook Price: $23.99
Book Price: $39.99
See more
Select your format and quantity:

About the Author :


Adam Griffiths

Adam Griffiths is a student and freelance CodeIgniter Developer based in the United Kingdom. He has five years web development experience, the last two being largely influenced by CodeIgniter. He has worked on many websites, both large and small, from small blogs to large multi-national companies. He is well versed in development techniques and how to squeeze that little bit more from an application. He has also made a number of contributions to the CodeIgniter Community, most notably The Authentication Library, a very simple-to-use but full-featured Authentication Library for CodeIgniter.

When CodeIgniter and PHP aren't spiralling around his head, Adam enjoys practising card and mentalist tricks, mainly sleight of hand and card handling. He has performed at local and formal functions for hundreds of people. He is also a guitar player and enjoys playing acoustically at pubs and small gigs. Moving back towards computing, he has a deep interest in Cryptography. He loves finding patterns in data and loves using pen and paper to decipher any cipher text he may find around the web.

Books From Packt


jQuery 1.4 Reference Guide
jQuery 1.4 Reference Guide

MooTools 1.2 Beginner's Guide
MooTools 1.2 Beginner's Guide

Plone 3 Products Development Cookbook
Plone 3 Products Development Cookbook

Magento 1.3: PHP Developer's Guide
Magento 1.3: PHP Developer's Guide

Spring Python 1.1
Spring Python 1.1

NetBeans Platform 6.9 Developer's Guide
NetBeans Platform 6.9 Developer's Guide

NHibernate 2 Beginner's Guide
NHibernate 2 Beginner's Guide

Agile Web Application Development with Yii1.1 and PHP5
Agile Web Application Development with Yii1.1 and PHP5


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software