Facebook PHP SDK and CodeIgniter for basic user authentication

With CodeIgniter 2.0, plugins are no longer an option. Usually you would just add the Facebook PHP SDK as a plugin and you were good to go, but now, you need to make a little modification to the SDK in order to use Facebook Connect on your CodeIgniter application. Lets start by explaining what is, how to get started and how to authenticate an user using the Facebook API.

Important: Facebook released a new SDK (version 3.0+) that dropped cookie support. This means, that the new SDK will not work with the XFBML buttons or the JavaScript SDK we are used to. For the new SDK to work, we have 2 options:

a) Use the standard login and logout URL that redirects the user to Facebook and then back to our site.
b) Modify the FB SDK to allow the use of cookies, which inherently allow us to us the JavaScript SDK and the cute FB login button plugin. As far as I know, the Facebook guys are working on re-implementing this feature on their SDK, but I don’t know when that’s going to happen.

In this article I will cover only the first case. Editing the Facebook SDK to support cookies takes a bit more work and it will be covered in a different post once I finish doing some testing (yes, I am working on my own implementation).

Update: Facebook updated the SDK to support cookies again. So, we can go back and use the JavaScript SDK or even XFBML for the login and logout buttons.

In this post I will only cover the user authentication process using the Facebook PHP SDK. However, you can do almost anything with the API, just take a look at the official documentation if you have any doubts:
http://developers.facebook.com/docs/reference/api/

All the methods related to the user object (very useful): http://developers.facebook.com/docs/reference/api/user/

First of all, a couple of links so you can download the necessary files:
CodeIgniter Reactor: http://www.codeigniter.com
Facebook PHP SDK: https://github.com/facebook/facebook-php-sdk (download the 3 files inside the /src/ folder).

Once you have your CodeIgniter set up, you can proceed to modify the Facebook PHP SDK and make it a library. What you need to do is:

  1. Autoload the CodeIgniter Session Library from application/config/autoload.php
  2. Facebook will try to pass the signed request via GET to your application. So, please make sure your CodeIgniter installation is set to allow the GET array. To do this, find the $config['allow_get_array'] in your application/config.php file and set it to true.
  3. Once you download the FB SDK, go to the “src” folder of the downloaded package and copy the “facebook.php”, “base_facebook.php” and “fb_ca_chain_bundle.crt” files to your CI application/libraries folder.
  4. Rename the file “facebook.php” to “Facebook.php” (notice the F in capital) present in your application/libraries folder.
  5. Add the following line to the beginning of the “Facebook.php” file:
    if ( ! defined('BASEPATH')) exit('No direct script access allowed');
    

The next step is to build a model that will handle the authentication process. It basically requests the session data and saves it into a CI session var. The view and the controller can take care of the rest.

<?php
class Facebook_model extends CI_Model {

	public function __construct()
	{
		parent::__construct();

		$config = array(
						'appId'  => 'XXXXXXXXXXXXXXXXXXX',
						'secret' => 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX',
						'fileUpload' => true, // Indicates if the CURL based @ syntax for file uploads is enabled.
						);

		$this->load->library('Facebook', $config);

		$user = $this->facebook->getUser();

		// We may or may not have this data based on whether the user is logged in.
		//
		// If we have a $user id here, it means we know the user is logged into
		// Facebook, but we don't know if the access token is valid. An access
		// token is invalid if the user logged out of Facebook.
		$profile = null;
		if($user)
		{
			try {
			    // Proceed knowing you have a logged in user who's authenticated.
				$profile = $this->facebook->api('/me?fields=id,name,link,email');
			} catch (FacebookApiException $e) {
				error_log($e);
			    $user = null;
			}
		}

		$fb_data = array(
						'me' => $profile,
						'uid' => $user,
						'loginUrl' => $this->facebook->getLoginUrl(
							array(
								'scope' => 'email,user_birthday,publish_stream', // app permissions
								'redirect_uri' => '' // URL where you want to redirect your users after a successful login
							)
						),
						'logoutUrl' => $this->facebook->getLogoutUrl(),
					);

		$this->session->set_userdata('fb_data', $fb_data);
	}
}

Now the controller(s). Here, you just have to load the Facebook model and validate the session vars accordingly:

class Home extends CI_Controller {

	function __construct()
	{
		parent::__construct();

		$this->load->model('Facebook_model');
	}

	function index()
	{
		$fb_data = $this->session->userdata('fb_data'); // This array contains all the user FB information

		if((!$fb_data['uid']) or (!$fb_data['me']))
		{
			// If this is a protected section that needs user authentication
			// you can redirect the user somewhere else
			// or take any other action you need
			redirect('login');
		}
		else
		{
			$data = array(
					'fb_data' => $fb_data,
					);

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

For the view we will use the native FB SDK login/logout URLs which are supported by default:

<body>
<div>
  <?php if(!$fb_data['me']): ?>
  Please login with your FB account: <a href="<?php echo $fb_data['loginUrl']; ?>">login</a>
  <!-- Or you can use XFBML -->
  <div class="fb-login-button" data-show-faces="false" data-width="100" data-max-rows="1" data-scope="email,user_birthday,publish_stream"></div>
  <?php else: ?>
  <img src="https://graph.facebook.com/<?php echo $fb_data['uid']; ?>/picture" alt="" class="pic" />
  <p>Hi <?php echo $fb_data['me']['name']; ?>,<br />
    <a href="<?php echo site_url('topsecret'); ?>">You can access the top secret page</a> or <a href="<?php echo $fb_data['logoutUrl']; ?>">logout</a> </p>
  <?php endif; ?>
</div>
</body>

This is a rough example of basic Facebook user authentication for your site. You can do a lot more and once you get a hang of it, it becomes pretty easy to work with. If there’s any doubts or questions, don’t hesitate to fill the comments section below, I’ll be happy to help.

Download the sample code.

Update Mar 1st, 2012: information on the new SDK. Also added a small update for custom permissions on the login URL. Requested by Alexintosh.

Update June 13th, 2011: Updated for the Facebook PHP SDK 3.0 +

Update May 3rd, 2011: Some servers seem to fail on cURL SSL certificates. To fix it, open the base_facebook.php file and find “CURLOPT_USERAGENT” (around line 132). Below that line add this:

CURLOPT_SSL_VERIFYPEER => false,

    • Brynleif
    • June 13th, 2012 12:50pm

    Thank you very much for having uploaded this and for keeping it updated. I would be pretty lost without this. I am having a problem that I am unable to understand, I hope someone here would like to help me out.

    I have managed to log in to the CI-page with Facebook and I can see the username and the picture. So far so good. Everything I need seems to be stored successfully in the CI-session. But when I open the topsecret function in the welcome-controller, this data doesn’t seem to exist. The function begins with $fb_data = $this->session->userdata(‘fb_data’);, but when I echo $fb_data['uid'] I get 0. I go back to the welcome page, and everything works perfectly.

    Sessions are auto-loaded, so I don’t understand what is causing this. Does anyone see what I am missing?

    Thank you.

    • Kamaldeep Singh
    • June 17th, 2012 9:25am

    Hi Danny,

    Thanks for updations.I am creating facebook login app with Codeigniter.Login functionality is working fine with codeigniter but when m clicking on logout url(facebooklogout url),created url is fine (means all params are containing in url) but its redirect to me facebook.com and session doesnot destroyed.
    I had tried manually delete session by calling facebook->destroySession but this will delete facebook session from my site but not from facebook.com.
    Please provide me its solution.Its urgent basis for me. Thanks in advance.Hope you can understand my problem and try to give solution to me

    • SImon Barker
    • June 21st, 2012 1:12pm

    Hi Danny,

    This tutorial has been invaluable in getting facebook login working on my side project so thank you for writing it, but I am having issues making the session data persist.

    The only way that I can make the $fb_data persist is to load the model in the construct of my controller class. This means that operations which work regardless of weather a user is logged in or not are slowed up by the GET requests made by the facebook class.

    This is a pain and means that I have to load the class on an as needed basis, rather than just for login and log out. Otherwise the session data does not persist. Why does the facebook session data not persist and can this be changed?

    Also, I noticed that when using this class the session ID is updated on every page refresh but not if it is removed.

    Any help in solving this issue would be great.

    Simon

  1. Everything is working fine apart from “Logout”, The logout link does not destroys the session. Does anyone has some idea?

    • pawel
    • July 4th, 2012 8:50am

    The login doesn’t work – It’s just linking to the current page – why?

    • Hi Danny.

      I am also getting same issue.It goes to Facebook App.After approval it comes to login page again.

      When I print_r($fb_data) $fb_data['uid'] is set to 0.

      I am not able to see picture or logout link.

      Thanks in advance.Please Help

      Regards,
      Abhijit

  2. I am having the same problem. can someone help me out from this?

    Brynleif :
    Thank you very much for having uploaded this and for keeping it updated. I would be pretty lost without this. I am having a problem that I am unable to understand, I hope someone here would like to help me out.
    I have managed to log in to the CI-page with Facebook and I can see the username and the picture. So far so good. Everything I need seems to be stored successfully in the CI-session. But when I open the topsecret function in the welcome-controller, this data doesn’t seem to exist. The function begins with $fb_data = $this->session->userdata(‘fb_data’);, but when I echo $fb_data['uid'] I get 0. I go back to the welcome page, and everything works perfectly.
    Sessions are auto-loaded, so I don’t understand what is causing this. Does anyone see what I am missing?
    Thank you.

  3. it never logout

    • amard
    • August 27th, 2012 2:32am

    logoutUrl only logout user from facebook account, it does not clear your site session data. you need to call codeigniter sess_destroy()

      • David
      • September 27th, 2012 2:27am

      Hi, I have tried this, and still can’t seem to get the logout function to work as I expect. I expect it should reload the welcome view (through the index function in the welcome controller) and show the login link once again.
      When I click the logout link, yes I get logged out of fB, and yes the welcome page reloads, but it still shows the link to the secret page.
      Any ideas?

  4. A PHP Error was encountered
    Severity: Notice

    Message: Undefined property: Welcome::$session

    Filename: core/Model.php

    Line Number: 51

    Fatal error: Call to a member function set_userdata() on a non-object in C:\APM_Setup\htdocs\app_name\application\models\facebook_model.php on line 47

    • Pete
    • October 5th, 2012 10:18am

    To fix logout you can simply add a new controller which will be the same as the 1st one only that you can add a new function:

    function logout()
    {
    session_start();
    session_unset();
    session_destroy();
    session_write_close();
    setcookie(session_name(),”,0,’/');
    session_regenerate_id(true);
    redirect(‘welcome’,'refresh’);
    } // end of logout

    Also you need to fix the views so as to call the new controller’s function:
    NEW_CONTROLLER_NAME/logout

    and remove or comment out the load of the model:

    $this->load->model(‘Facebook_model’);

  5. Thank you very much – we use it in many projects for our customers.

    • Ryan
    • October 21st, 2012 7:25pm

    I also get blank/0 $this->session->userdata(‘fb_data’). Any solution? This worked once and then never worked again, although the code didn’t change.

    • Ryan,

      Try and update the SDK. Download it again from Github and give it a shot. That SDK has changed recently. However, the CodeIgniter code should remain the same.

    • Tom
    • November 8th, 2012 1:38pm

    Hi Danny
    Thanks for this – great work.

    Will this work if I combine the JS SDK for login and the PHP SDK for the rest? If so could you give me an example?

    Cheers

  6. Thanks for this, it was very useful.

    • ardi
    • January 8th, 2013 5:12am

    hey danny.. the code is work at localhost but when i am implementing at app facebook its not working..the uid return 0 and me profile is null…any solution??

  7. ardi :

    hey danny.. the code is work at localhost but when i am implementing at app facebook its not working..the uid return 0 and me profile is null…any solution??

    This happened to me a few days ago in an old app. It was because I didn’t have the latest Facebook PHP SDK and SSL certificate installed. Can you please download and install the latest SDK? Also make sure you are using sessions, that the app URL is properly configured on Facebook and that the app permissions have been accepted.

    • ardi
    • January 10th, 2013 2:42am

    hmm..i already use latest facebook php sdk and i already check ssl certificated have successful installed. maybe the problem is session, or app configuratuin

    • ardi
    • January 10th, 2013 10:42pm

    any solution danny? how to make sure i’m using sessions properly and app url is properly configured?

    • ardi
    • January 15th, 2013 6:52am

    if my app Curl enabled can make this error solved??because my app curl is not enabled now??need answer :D

follow me on Twitter