How to Authenticate Users With Facebook Connect

How to Authenticate Users With Facebook Connect

Tutorial Details
  • Difficulty: Intermediate
  • Completion Time: 45 Minutes

Lately, there’s been quite a fuzz about lazy registration. It turns out that the less the user has to think, the higher the conversion rates are! What a thought! If everybody seems to have a Facebook profile, why not add a one-click user registration? I’ll show you how to do that today.


Step 1. The Setup

MySQL Table

Let’s begin by creating a database table.

CREATE TABLE `users` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `oauth_provider` varchar(10),
    `oauth_uid` text,
    `username` text,
    PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;

Quite simple: we will be setting up a table for user information with id, username, first and last name, the URL to the user’s picture, and registered date. Also, we’re adding both an oauth_provider and oauth_uid fields, to distinguish between different third party open authentication protocols and their identifiers. For example, let’s say that, next week, you decide that it’s a good idea to also let Twitter users in. Easy; you just set another value to the oauthprovider, and avoid duplicating oauthuid values.

The Facebook App

Let’s begin by creating a new application. Give it a name and agree to the terms and conditions. Next, grab both the API Key and Secret in the basic tab as shown below.

On the canvas tab, set both the Canvas URL and Post-Authorize Redirect URL to your localhost and path that the script will process — something like http://localhost.com/login_facebook.php?. Note the question mark at the end and the domain; both are required by Facebook. Simply set your hosts file to a valid domain name.

On the connect tab, set the Connect URL to the same value and set localhost.com (or the one you are using) as the Base Domain.

Now save, download the client library, and unzip facebook.php in the srcdir to a new directory created in the root.


Step 2. The Callback

The authentication flow has three steps:

  1. The local script generates a URL asking the user for permission
  2. Facebook returns to the Canvas URL specified with a GET parameter
  3. The GET parameter authenticates the session

Let’s make a quick test before registering and login.

# We require the library
require("facebook.php");

# Creating the facebook object
$facebook = new Facebook(array(
    'appId'  => 'YOUR_APP_ID',
    'secret' => 'YOUR_APP_SECRET',
    'cookie' => true
));

# Let's see if we have an active session
$session = $facebook->getSession();

if(!empty($session)) {
    # Active session, let's try getting the user id (getUser()) and user info (api->('/me'))
    try{
        $uid = $facebook->getUser();
        $user = $facebook->api('/me');
    } catch (Exception $e){}

    if(!empty($user)){
        # User info ok? Let's print it (Here we will be adding the login and registering routines)
        print_r($user);
    } else {
        # For testing purposes, if there was an error, let's kill the script
        die("There was an error.");
    }
} else {
    # There's no active session, let's generate one
    $login_url = $facebook->getLoginUrl();
    header("Location: ".$login_url);
}

Now, go to http://localhost.com/login_facebook.php, and let’s see what happens. If you are redirected to Facebook and requested for permission, we are on the right track.

However, there might be two issues. The first one: if you’re redirected to Facebook, but it shows an error, there might be a missing value in the configuration. Go back to your application settings and check both the Connect and Canvas tabs and make sure the fields are ok as described above.

There might be another issue, where you see an error, like “Uncaught CurlException: 60: SSL certificate problem, verify that the CA cert is OK.” This happens because of the CURL settings. You’ll have to open facebook.php, find the makeRequest() method, and, inside the function, find this line:

$opts = self::$CURL_OPTS;

Immediately following it, add:

$opts[CURLOPT_SSL_VERIFYPEER] = false;

I hate hacking libraries, but I haven’t found another way. Well, let’s continue with user registration. I’ve also added a try/catch statement, because, if there’s an old session keys in the GET params in the URL, the script will die with a horrible error.


Step 3. Registration and Authentication

We’ll next be working with MySQL. Please note that I will not implement a data sanitizer, since I want to keep the code as short and on task as possible. Please keep this in mind: always sanitize your data.

First, let’s connect to the database.

mysql_connect('localhost', 'YOUR_USERNAME', 'YOUR_PASSWORD');
mysql_select_db('YOUR_DATABASE');

Now, let’s work on the $session conditional, in case we have a session.

# We have an active session; let's check if we've already registered the user
$query = mysql_query("SELECT * FROM users WHERE oauth_provider = 'facebook' AND oauth_uid = ". $user['id']);
$result = mysql_fetch_array($query);

# If not, let's add it to the database
if(empty($result)){
    $query = mysql_query("INSERT INTO users (oauth_provider, oauth_uid, username) VALUES ('facebook', {$user['id']}, '{$user['name']}')");
    $query = msyql_query("SELECT * FROM users WHERE id = " . mysql_insert_id());
    $result = mysql_fetch_array($query);
}

Note that I’m querying the database, looking for facebook as a oauth_provider; it’s generally a good idea, if you want to accept other OAuth providers (as twitter, Google Accounts, Open ID, etc.) and a oauth_uid, since it’s the identifier the provider gives to its user accounts.

The oauth_provider field could potentially lead to bad performance if we leave it as a text field type. As such, the best option is setting it to an ENUM type.

We have now a $result var with the values queried from the database. Let’s next add some sessions. Add this line at the beginning of your script.

session_start();

After the empty($result) conditional, append the following:

if(!empty($user)){
    # ...

    if(empty($result)){
        # ...
    }

    # let's set session values
    $_SESSION['id'] = $result['id'];
    $_SESSION['oauth_uid'] = $result['oauth_uid'];
    $_SESSION['oauth_provider'] = $result['oauth_provider'];
    $_SESSION['username'] = $result['username'];
}

As it makes little sense to authenticate a user who is already logged in, just below the session_start() line, add:

if(!empty($_SESSION)){
    header("Location: home.php");
}

And in the scripts which require authentication, just add:

session_start();
if(!empty($_SESSION)){
    header("Location: login_facebook.php");
}

And if you want to display the username, access it as an array.

echo 'Welcome ' . $_SESSION['username'];
# or..
echo 'Welcome ' . !empty($_SESSION) ? $_SESSION['username'] : 'guest';

Step 4. Additional Methods

Facebook has a ton of connect features, but here are four that I’ve found to be the most useful.

Legacy Methods

I might be missing something, but the FQL seems more flexible and easy than the Graph API. Fortunately, Facebook still lets developers use it, altough with the new library, it has changed a bit.

If you want the user id, first name, last name, squared thumbnail for the user picture, the biggest user picture available, and his or her gender, you can use the users.getInfo method.

    $uid = $facebook->getUser();
    $api_call = array(
        'method' => 'users.getinfo',
        'uids' => $uid,
        'fields' => 'uid, first_name, last_name, pic_square, pic_big, sex'
    );
    $users_getinfo = $facebook->api($api_call);

You can check the full list of fields available for Users.getInfo.

It is possible to achieve the same result, using FQL.

    $uid = $facebook->getUser();
    $fql_query  =   array(
        'method' => 'fql.query',
        'query' => 'SELECT uid, first_name, last_name, pic_square, pic_big, sex FROM user WHERE uid = ' . $uid
    );
    $fql_info = $facebook->api($fql_query);

Here’s the list of tables which can be accessed with FQL, as well as the fields available for the table users.

Extended Permissions

Facebook provides applications with some interaction with the user’s data – just as long as it’s authorized. With the old API, the authorization for additional permissions was exclusively available for the Javascript SDK (altough I’m not quite sure). With the new API, we can easily redirect the user to an authorization dialog in Facebook, and return to our site after the access is either granted or denied.

In the following example, we will be redirecting a user to authorize posts status updates, photos, videos and notes, the user’s real email address, birthday and access to photos and videos.

$uid = $facebook->getUser();

# req_perms is a comma separated list of the permissions needed
$url = $facebook->getLoginUrl(array(
    'req_perms' => 'email,user_birthday,status_update,publish_stream,user_photos,user_videos'
));
header("Location: {$url} ");

Here’s a full list of permissions. Note that you can specify both the url to direct to if the user accepts and the url to be redirected to if the user denies. The key for these array elements are next and cancel_url, respectively. Here’s a quick example:

$url = $facebook->getLoginUrl(array(
    'req_perms' => 'email',
    'next' => 'http://localhost.com/thanks.php',
    'cancel_url' => 'http://localhost.com/sorry.php'
));

If not specified, the default is the requesting script’s location.

Checking for Extended Permissions

Since the user can easily revoke permissions, the application should always check if a given permission is granted before using it, specially if it’s about publishing something. We will have to use the legacy API, as it seems it’s not fully implemented with the new one yet.

    $uid = $facebook->getUser();

    # users.hasAppPermission
    $api_call = array(
        'method' => 'users.hasAppPermission',
        'uid' => $uid,
        'ext_perm' => 'publish_stream'
    );
    $users_hasapppermission = $facebook->api($api_call);
    print_r($users_hasapppermission);

The ext_perm will only support the old list of available permissions.

Publishing to the Wall

Let’s post something to the wall after verifying the user has the publish_stream permission.

    # let's check if the user has granted access to posting in the wall
    $api_call = array(
        'method' => 'users.hasAppPermission',
        'uid' => $uid,
        'ext_perm' => 'publish_stream'
    );
    $can_post = $facebook->api($api_call);
    if($can_post){
        # post it!
        $facebook->api('/'.$uid.'/feed', 'post', array('message' => 'Saying hello from my Facebook app!'));
        echo 'Posted!';
    } else {
        die('Permissions required!');
    }

Essentially, we are making an API call to /<user_id>/feed, using the POST method (second argument) and an array as a third argument for the data to be sent. In this case, this third argument supports message, link, picture, caption, name and description. Here’s the code:

$facebook->api('/'.$uid.'/feed', 'post', array(
    'message' => 'The message',
    'name' => 'The name',
    'description' => 'The description',
    'caption' => 'The caption',
    'picture' => 'http://i.imgur.com/yx3q2.png',
    'link' => 'http://net.tutsplus.com/'
));

Here’s how it is posted.

Some Additional Information you Should Know:

The user can easily revoke permissions with two clicks in his or her wall. You should heavily test what might happen if a user revoked one or more permissions that are vital for the proper functioning of your website, or even if the application is fully removed. This is important.


5. Conclusion

While Facebook’s authentication capabilities are indeed useful, since so many people are on Facebook these days, using it as the only method of authentication in a site is not recommended. What about those who don’t have Facebook accounts? Are they not allowed to access your application? Thanks for reading!

Rafael Soto is faelsoto on Codecanyon
Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://www.kloude.net Kloude

    Thanks for this, we are working on developing this for our users as an option to access their account on our end.

  • vista-design

    great tutorial rafael

    idk why the facebook doesn’t load the creat app page and when didn’t give me the page of app id and secret

  • http://www.juxt2.com Dimitree

    What happens If a user later decides to remove the application? How can we erase his records from the Database?

    • http://www.yariok.com Yari

      Hi Dimitree take a look a this:

      http://wiki.developers.facebook.com/index.php/Post-Remove_Callback_URL

      In a few words, you can define a callback url which will be called (in POST!!) when user uninstal your app. So at this url you can specify some database clean procedure.

      Yari

      • Enrique

        have you tested it? I did and it’s not working to me, I receive the call to my Callback URL, but $_POST is empty always.
        I’m not the only one with this problem, but I couldn’t find any solution.
        Is it working the Post_Remove_Callback_URL in your application?

  • http://www.justni.com chris mccabe

    You have a typo error in this tutorial

    after-

    # If not, let’s add it to the database
    if(empty($result)){
    $query = mysql_query(“INSERT INTO users (oauth_provider, oauth_uid, username) VALUES (‘facebook’, {$user['id']}, ‘{$user['name']}’)”);
    $query = msyql_query(“SELECT * FROM users WHERE id = ” . mysql_insert_id());

    the second query should be

    $query = mysql_query

    • nhdongphuong

      the typo error is on line # 48

  • trojan

    thanks, good tutorial
    It was of great help

  • Gorm Frederiksen

    Thanks a bunch! – this tutorial saved my ass

  • http://classicaspreference.com Lil

    Bravo! Finally! A tutorial I can understand, with examples that are easy to customize for my own needs. Awesome!

  • http://www.edesignerz.net/ EDESIGNERZ.NET

    Awesome tutorial! Easy to understand and high class. Thanks Tutsplus!

  • Justin Cribb

    I wonder if it is also possible saving the access token in Javascript SDK. There is no next and cancel parameter in Javascript SDK…hmmm…I don’t know how to do the same thing using Javascript SDK. Thanks for the PHP Tutorial.

  • rahul shukla

    looking for logout.php for facebook_login

  • rijesh

    I made it as a facebook application.But this is working for only owner of the application. when i try to access the application as another user through facebook , application is not returning the current user session.Please help me.

    • http://tilbudibyen.dk Dennis

      Hi, thanks for this facebook “app” anyway, its not really working. anyone got it working right? i got errors like a few others in here.
      and if i just google chrom it just got to my redirect page and nothing happens.

      hope some one would make something that really worked. everyone is asking for it, but not many got it working.

      pls someine help.

  • http://www.jsxtech.com Jaspal Singh

    Great post with simple code to authenticate users with Facebook Connect.
    Thanks for sharing.

  • vicky

    I got this error how to remove this “Firefox has detected that the server is redirecting the request for this address in a way that will never complete.This problem can sometimes be caused by disabling or refusing to accept cookies.”

  • kamran

    How can we send send post if user is not logged in his facebook account

  • niureex

    vicky says:
    August 4, 2010 at 12:47 pm

    I got this error how to remove this “Firefox has detected that the server is redirecting the request for this address in a way that will never complete.This problem can sometimes be caused by disabling or refusing to accept cookies.”

    i got this prob also.. can someone try to fix this please…

  • http://www.9lessons.info Srinivas Tamada

    Thanks a lot. Great tutorial

  • Michael

    I am getting the same error with the redirecting request never completing. It started when I tried to get extended permissions, the login seemed to work fine.

    Any help please?

  • Michael

    It seems it is actually granting the permissions, but it doesn’t resolve properly when it gets to facebookuid or whatever it is.

  • Ben

    It’s clearly an issue with your readers that your code is creating a loop. You have acknowledged it yourself in the comments and offered no solution. While I understand you did this off your own back and it has helped a little, you have left huge holes that, when combined with how severely lacking the facebook documentation is, leaves people that are trying to learn running round in circles. The forums are saturated with unanswered questions and the fact that there are seemingly so many wrong ways of doing something means it’s impossible to get an answer.

    Can you please address the redirect issue? Otherwise, what’s the point in writing a tutorial? Inettuts is so frustratingly blase with some of their stuff, sometimes I wonder how much more harm than good this site does. Certainly puts me off a premium membership.

    Seriously, can you address the redirect issue? I can’t do anything about it if I can’t even find what it is meant to be doing int the first place.

  • andoy

    hi to all of you guys!

    I get an error when I try to run my facebook application. I am new to PHP and would like to learn more on it.

    And I am also using a free webhosting site.

    Fatal error: Uncaught exception ‘Exception’ with message ‘Facebook needs the CURL PHP extension.’ in /www/../andoy/htdocs/php_test/facebook.php:4 Stack trace: #0 /www/..andoy/htdocs/php_test/index.php(5): require() #1 {main} thrown in /www/../andoy/htdocs/php_test/facebook.php on line 4

    Thanks for any comment.

    I’d appreciate it.

    • http://blog.sergiorus.com Sergio

      you need to install curl for php5:

      sudo apt-get install curl libcurl3 libcurl3-dev php5-curl php5-mcrypt

      • Nagarjun

        Where do we type this?

      • Dave

        in the ubuntu terminal

  • andoy

    by the way.. thanks for the great tuts..

  • http://aionstatus.com/ Ashley Snowdon

    To those going on about the redirect loop:

    The reason it’s looping is because there is no initial check to see if the user already has the permission you’re requesting for.

    Just add an API call for the permission you’re checking. If it’s 0, then make the request.

  • http://www.ta3lime.com التعليم نت

    It seems it is actually granting the permissions, but it doesn’t resolve properly when it gets to facebookuid or whatever it is.

  • Keladi

    header(“Location: {$url} “); is no longer working..

  • http://crilance.blogspot.com Cristian Rusu

    Hello

    Is there a way to verify the response authenticity from Facebook in order to prevent someone posting back to my script with mangled GET values….

    Maybe the session key or some sort of secret to be checked against actual FB application?

    Thanks
    Cristian

  • http://www.matemerge.com Vidhyatharan Kumaravelu

    thanks a heap .. ive been looking all over the place for a decent tutorial to help me integrate facebook connect .. thanks again, your a legend!!

  • http://www.anildewani.com Anil Dewani

    Header redirect won’t work anymore if you are integrating it to a canvas page of application.
    Maybe, is there anyway of other redirections ?

  • Ian

    I know this tutorial is a bit outdated and it’s not exactly the intent of this tutorial to do this, but can anyone tell me how I can modify this so that it redirects back to the facebook app itself rather than my website?

    Every time I try to make it redirect back it just keeps bringing up the “log into facebook” page, despite having already given it permissions. Any help at all would be appreciated.

  • Max

    Why …… fields => ‘ current_location’ value not appear?

    1. $uid = $facebook->getUser();
    2. $api_call = array(
    3. ‘method’ => ‘users.getinfo’,
    4. ‘uids’ => $uid,
    5. ‘fields’ => ‘uid, first_name, last_name, pic_square, pic_big, sex, current_location’
    6. );
    7. $users_getinfo = $facebook->api($api_call);

  • http://marysocoortiz.com Hakel

    Hey!
    Thanks a lot! this is a great, great tutorial, easy and very understandble.
    It was so helpful for my application! thanks!

  • mctaco

    Muy buen tutorial! De lo mejor que he encontrado y bien explicado :)

  • http://evoadds.com ev0

    Most amazing tutorial i’ve found, with such simple instructions. Thanks a ton for the perfect information for me to set up my site!

  • http://simpletutors.com Shah Alom

    Thanks for the great tutorial. I am looking for such a tutorial for last 10 days. It really works. Thanks Again.

  • David

    Thanks for this post, saved my hide man!

  • http://www.neek6.com/ سكس

    thanks for this tutorial

  • http://www.bizclickr.com John

    This worked very well. I used it in conjunction with Facebook register on the homepage of my website. I was able to get the UID from my own login. Is there a way to also get the email address of the Facebook user? I need to send that to our database so that the application they will be using in Facebook can show their Bizclickr.com content.
    I added a $email variable and put it in the list for INSERTING into MySQL, but the field is empty. Is there another attribute that I need to introduce into the PHP page?

    Thanks!

  • Nagarjun

    I get the following errors in Step 2.

    1. Fatal error: Uncaught exception ‘Exception’ with message ‘Facebook needs the CURL PHP extension.’ in C:\wamp\www\helloPlane\facebook.php on line 4

    2. Exception: Facebook needs the CURL PHP extension. in C:\wamp\www\helloPlane\facebook.php on line 4

  • Dave

    Hey developers…

    I’m thinking for those dudes who get an “there was an error” error message, i think this occurs when you change the SITE URL text field in the Facebook developer page,most probably your changes haven’t been propagated to all the servers…it does work after a while though

  • Dave

    if you are using Linux, follow the instructions on the comments posted in the previous page: download the curl extension: apt-get install libcurl3

    type that in the terminal.

    or go here:

    http://www.tildemark.com/programming/php/enable-curl-with-xampp-on-windows-xp.html

    hope this helps…
    all the best

  • Anes P A

    Hi Friends,
    I work According to you , But I got a Blank page with it’s URL pointing to : http://www.facebook.com/developers/login_error.php?app_id=188688331164433&connect=1&type=connect

    why this ? Please Advise Where I wrong and reply me with your ideas immediately in my email :
    anes(dot)pa(at)gmail(dot)com …

    Thankfully,
    Anes P.A

  • mathias

    When i try to go to login_facebook.php as described in step 2, i get
    “unexpected ‘{‘ at line 18″
    this is right after “try”

  • http://fenonit.co.uk Rich

    Facebook have changed there ways of facebook connect, any chance of this tutorial being updated?

    Thanks

    • Daniel

      I´m wondering the same thing.

      Thanks in advance!

    • http://stefanow.net Stefan

      “If you are redirected to Facebook and requested for permission, we are on the right track.” – http://i273.photobucket.com/albums/jj226/stefek99/facebook-connect.png

      Additionally: “On the connect tab, set the Connect URL” – no connect tab… :]

      Probably some changes occurred. Update is necessary! :)

  • DrLightman

    with id, username, first and last name, the URL to the user’s picture, and registered date

    There are no such columns in the MySQL table definition provided :)

  • fern

    I want to grab user id when user accept my permission and store user id in database. anybody please help me!

  • http://www.danapplegatedesign.com Dan Applegate

    “There might be another issue, where you see an error, like “Uncaught CurlException: 60: SSL certificate problem, verify that the CA cert is OK.” This happens because of the CURL settings. You’ll have to open facebook.php, find the makeRequest() method, and, inside the function, find this line: … I hate hacking libraries, but I haven’t found another way.”

    Hi Rafael, thanks for the tutorial.

    Regarding your solution for turning of cURL’s peer verification. The CURL_OPTS array in the Facebook class is a public static field, so it’s modifiable from your own code. if you notice in the makeRequest() method, Facebook uses whatever options are set in its CURL_OPTS array, then adds to them. So, this would achieve what you want:

    Facebook::$CURL_OPTS[CURLOPT_SSL_VERIFYPEER] = false;
    $facebook = new Facebook(array(
    ‘appId’ => ‘YOUR_APP_ID’,
    ‘secret’ => ‘YOUR_APP_SECRET’,
    ‘cookie’ => true
    ));

    Or, an even better solution which achieves better encapsulation would be to extend the Facebook class and override the constructor, setting your custom cURL options, like this:

    class MyFacebook extends Facebook {

    const APP_ID = ‘YOUR_APP_ID’
    const APP_SECRET = ‘YOUR_APP_SECRET’

    public function __construct() {
    // Turn off SSL certificate checking
    parent::$CURL_OPTS[CURLOPT_SSL_VERIFYPEER] = false;
    parent::__construct(array(
    ‘appId’ => self::APP_ID,
    ‘secret’ => self::APP_SECRET,
    ‘cookie’ => true,
    ));
    }
    }

    Then, you would instantiate your custom Facebook class and use that instead of the default one:

    $facebook = new MyFacebook;

  • http://leetlikes.com Mason

    Fantastic Tutorial, But only one problem.
    Every time anyone goes to http://leetlikes.com/login_facebook.php it just comes up with “There was an error”

    How can I fix this?

  • http://variable3.com/ Harsha M V

    Am having trouble logging out of the Facebook Connect.

    I am destroying the session and logging out this way
    $this->Session->destroy();
    $this->redirect($this->Auth->logout());

    am using cakephp.

    when i logout of facebook.com

    and still click facebook login. its still logs in – even though am logged out on facebook.com

    • http://www.ccastig.com Chris

      Hey Harsha, I think you just need to “start session” before you “destroy session”. Hope that works. (worked for me)

  • nakres

    hi, i would like to add my web page to Facebook as an application but i have a database for my users how can i integrate it or add/register facebook users or signed them automatically as an registered users so they can access my site

    thank you

  • Ajeesh

    Hi there,

    I must say this is the Best tutorial of all the Facebook App development.

    But have a problem, After executing the statement

    $facebook->api(‘/’.$uid.’/feed’, ‘post’, array(‘message’ => ‘Saying hello from my Facebook app!’));

    in the http://www.myserver.com/thanks.php

    In the browser is redirected to this page. And it is “NOT” going back to Facebook App interface.

    Did I do something wrong ? Or do I have to do anything to redirect back to the Facebook App interface?

    Thanks – Ajeesh

  • C

    Hi guys, Facebook has updated its API and this tutorial is now outdated, any plans to update it? :)