How to Authenticate Users With Facebook Graph In CakePHP

Facebook Graph API, drastically simplify the way developers read and write data to Facebook. It presents a simple, consistent view of the Facebook social graph, uniformly representing objects in the graph (e.g., people, photos, events, and pages) and the connections between them (e.g., friend relationships, shared content, and photo tags).

home1 How to Authenticate Users With Facebook Graph In CakePHP

There is a lot of tutorial out there that talking about how to authenticate user using Facebook Graph API. Today I will share with you simple tutorial how to authenticate user using Facebook Graph API in cakephp based on my experience.

MySQL table.

CREATE TABLE `users` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `oauth_provider` varchar(10) default NULL,
  `oauth_uid` varchar(64) default NULL,
  `access_token` text,
  `username` text,
  `created` datetime default NULL,
  `modified` datetime default NULL,
  PRIMARY KEY  (`id`),
  KEY `oauth_uid` (`oauth_uid`)
) ENGINE=MyISAM AUTO_INCREMENT=15 DEFAULT CHARSET=latin1

oauth_provider is from where user registered come from, for example facebook, twitter etc. oauth_uid is the user id given by oauth provider.

Facebook App

Register your application to get an app ID and secret, give it name and click agree, grab the API Key and Application Secret.

create facebook app How to Authenticate Users With Facebook Graph In CakePHP

Go to website tab, fill Site URL with your application url, for axample http://localhost/fboauth?.

app setting How to Authenticate Users With Facebook Graph In CakePHP

CakePHP

You need to downloade CakePHP Framework. The latest version when im writing this tutorial is 1.3.5 version. On core.php (/app/config/core.php) , change the value of ‘Security.salt’ and ‘Security.cipherSeed’.

Rename database.default.php (/app/config/database.default.php) to database.php, and set the database connection.

class DATABASE_CONFIG {
var $default = array(
'driver' => 'mysql',
'persistent' => false,
'host' => '127.0.0.1',
'login' => 'root',
'password' => 'root',
'database' => 'fboauth',
'prefix' => '',
);
}

Facebook Graph API

Grab the New Facebook Graph API from GitHub. Copy the facebook.php to /app/vendor/.

Baking

Lets simplify the creation of model, view and controller using CakePHP Bake.

Login, Callback, Logout, Home

After baking, we have all model, controller and view for our app, including for the admin. Then we continue with adding login, callback, logout and home action on users_controller (/app/controller/users_controller.php).

class UsersController extends AppController {
var $name = 'Users';
#once application loaded, we will redirect to this controller
function home(){
}
function login(){
}
function callback(){
}
function logout(){
}
}
login

On login action, first, we need to import facebook sdk.

function login(){
//import facebook sdk
App::import('Vendor', 'facebook');
$facebook=new Facebook(array(
'appId'=>'ad249ee9b242c34e0921636128cxxxxx',
'secret'=>'12f1df2ddfe9e31085591b522ebxxxxx',
'cookie'=>true
));
#generate facebook session
$session=$facebook->getSession();
# generate login url
     		$login_url = $facebook->getLoginUrl(array(
'next' => 'http://localhost/fboauth/users/callback',
));
#if session available
if(!empty($session)){
$this->Session->write('uid',$session['uid']);
$this->Session->write('username',$session['name']);
$this->redirect(array('controller'=>'users','action'=>'home'),null,true);
}else{
$this->redirect($login_url);
}
}
callback

Callback is the action we will call or the url we will redirect once user authentication is success. The key is on ‘next’ => ‘http://localhost/fboauth/users/callback’, in login action.

function callback(){
App::import('Vendor', 'facebook');
$facebook=new Facebook(array(
'appId'=>'ad249ee9b242c34e0921636128cxxxxx',
'secret'=>'12f1df2ddfe9e31085591b522ebxxxx',
'cookie'=>true
));
$session=$facebook->getSession();
if(!empty($session)){
try{
$user=json_decode(file_get_contents('https://graph.facebook.com/me?access_token='.$session['access_token']));
}catch(FacebookApiException $e){
error_log($e);
}
if(!empty($user)){
//check user on users table by oauth_uid
$user_id=$this->User->findByOauthUid($user->id);
//if empty/ ser not found then insert into table
if(empty($user_id)){
$this->data['User']['oauth_provider']='facebook';
$this->data['User']['oauth_uid']=$user->id;
$this->data['User']['access_token']=$session['access_token'];
$this->data['User']['username']=$user->name;
if($this->User->save($this->data)){
$this->Session->write('uid',$user->id);
$this->Session->write('access_token',$session['access_token']);
$this->Session->write('username',$user->name);
$this->Session->setFlash(__('Your profile has been saved', true));
$this->redirect(array('controller'=>'users','action'=>'home'));
}else{
$this->Session->setFlash(__('Sorry, we could not save your profile. Please, try again.', true));
$this->redirect(array('controller'=>'users','action'=>'home'),null,true);
}
}else{
$this->Session->write('uid',$user_id['User']['oauth_uid']);
$this->Session->write('acces_token',$user_id['User']['access_token']);
$this->Session->write('username',$user_id['User']['username']);
$this->redirect(array('controller'=>'users','action'=>'home'),null,true);
}
}
}else{
$this->Session->setFlash(__('Sorry, we could not authenticate you.', true));
$this->redirect(array('controller'=>'fans','action'=>'home'),null,true);
}
}
Logout

The logout action is pretty simple, just destroy all session.

function logout(){
$this->Session->destroy();
$this->Session->setFlash('You have successfully logged out.');
$this->redirect(array('controller'=>'users','action' => 'home'));
}
home.ctp

Once application loaded we will redirect page to home.ctp. You can set this configuration in routes.php.

<div class="users home">
<h2><?php __('Users Home');?></h2>
<?php
$uid=$this->Session->read('uid');
if(!empty($uid)){
echo "<img src=\"https://graph.facebook.com/$uid/picture\"/>";
echo "<h3>Welcome ".$this->Session->read('username')."</h3>";
echo "</br>";
echo "</br>";
echo $this->Html->link('Logout',array('controller'=>'users','action'=>'logout'));
echo "</hr>";
}else{
echo $this->Html->link('Login',array('controller'=>'users','action'=>'login'));
}
?>
</div>
routes.php
Router::connect('/', array('controller' => 'users', 'action' => 'home'));

Conclussion

User Authentication using graph is pretty simple. Just make sure you set the right application setting. Once user authenticated and user data inserted into table, then you can playing arround with other API call. If your application need user email and application able to write on users wall, you can add extended permission by put additional extended permission on your login-url, ex:

$login_url = $facebook->getLoginUrl(array(
'req_perms' => 'email,user_birthday,status_update,publish_stream',
'next' => 'http://localhost/fboauth/users/callback',
));

Because of the demo file grab your access token, dont forget to delete your profile when you finish try the demo file by click here.

Incoming search terms for the article:

Related Posts

David Spillane Resigns As Facebook CAO

Client-Side Facebook App Login/Authorization

Facebook Partners With Telecom Networks To Provide Cheaper Messaging Overseas

Create A Twitter Timeline Using jQuery And CSS

15 Comments

  1. Peter Nore

    11.12.2010

    This tutorial helped me where tens of other tutorials were no longer applicable or didn’t quite work. For those of you who download the code and try it out, be sure to change a few things: 1.) modify the config/database.php to your mysql settings 2.) don’t configure your facebook app to http://localhost/fboauth, instead, make it http://facebooktest.domain.tld and have cake in root, 3.) modify app/controllers/users_controller so that the appId and secret are your own information - note that you must change the appId and the secret *twice* in the file, 4.) modify the url in line 23 of that same file so that it points to the callback action on your domain. That should do it! It is possible to get this to work in a localhost environment, but you have to configure your computer to accept incoming connections from facebook …

    • Mufti Ali

      11.12.2010

      Glad to this article useful for you, you can also write your app_id and app_secret once on core.php, ex:
      Configure::write(‘Facebook.app_id’,’159813000xxxxx’);
      Configure::write(‘Facebook.app_secret’,'ad6caf36b2bfcc46cc867cxxxxxx’);

      in the controller you just call like this:
      $facebook=new Facebook(array(
      ‘appId’=>Configure::read(‘Facebook.app_id’),
      ‘secret’=>Configure::read(‘Facebook.app_secret’),
      ‘cookie’=>true
      ));

  2. Amol Deshpande

    11.13.2010

    Hi, Thanks a lot for these steps. It help me out of my problem.

  3. Abhinav Sood

    11.17.2010

    Hello Mufti, Happy Eid Mubarak to you. Thank you for writing this wonderful tutorial.

    I am making a CakePHP application where I am trying to integrate Authentication with Facebook along with the normal username/password based authentication. I have a question and I’d be glad if you would help me.

    When I try to login using Facebook by the method you explained above, it gives me an error message that it cannot save the profile, for obvious reasons (it fails to create the user as password field cannot be left blank and email is required) . I suppose, we can generate a random password for users coming via Facebook. It won’t we used but we can just keep it there.

    How would I generate a password and store it in this case?
    Abhinav Sood´s last blog ..AbhinavSood- is looking for guides and assistants-contributors to a CakePHP based open-source ToDo app DM if interested and Plz RT! cakephp opensource My ComLuv Profile

    • Mufti Ali

      11.18.2010

      Let make assumption that you have password and email column on your users table, and you set email request permission (‘req_perms’ => ‘email’). You can use username or email and combined with ‘salt’ to create random password.
      if(empty($user_id)){
      $this->data['User']['oauth_provider']=’facebook’;
      $this->data['User']['oauth_uid']=$user->id;
      $this->data['User']['access_token']=$session['access_token'];
      $this->data['User']['username']=$user->name;
      $this->data['User']['email']=$user->email;
      $salt = Configure::read(‘Security.salt’);
      $this->data['User']['password']=md5($user->email.$salt);
      }

  4. rafael soto

    11.24.2010

    whoa, really good tutorial, but you should link to the sources, which is one of my tutorials on nettuts: http://net.tutsplus.com/tutorials/php/how-to-authenticate-your-users-with-facebook-connect/

    • Mufti Ali

      11.24.2010

      Hi, Rafael, before i write this tutorial, i follow your tutorial on nettuts but get this error “Firefox has detected that the server is redirecting the request for this address in a way that will never complete”.

  5. Alevsk

    12.20.2010

    Hi I want to congratulate you for this amazing cakePHP tutorial :) , currently Im developing an application that will use facebook connect, I followed all the instructions in this tutorial but cakephp didnt insert the new data user in the data base :( , also cakephp didnt show any error, I think the error is on the callback function, because when I push the login link the web is refresh and its appear that the user start session because the logout link is shown but in the welcome text does not appear the name. If I go manually to the /users/callback path I get this error:

    Warning (2): file_get_contents(https://graph.facebook.com/me?access_token=177173152307936|2.ZLWxF4wnq5EMRaq5t7OFVw__.3600.1292835600-1078496755|Z9K-2qq15ED1JjrjYGnt0MAUJew) [http://php.net/function.file-get-contents]: failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request
    [APP/controllers/users_controller.php, line 46]

    and in the linea 46 in the user_controller.php there is

    $user=json_decode(file_get_contents(‘https://graph.facebook.com/me?access_token='.$session'access_token'));

    I hope you can help me, of course if you have the chance :)

    salu2 from México

    • Mufti Ali

      12.20.2010

      Hi Alevsk, seem like “file_get_contents” not work n your server. Plese check your php.ini configuration, make sure allow_url_fopen = on. A common alternative is to use cURL.
      source: http://stackoverflow.com/questions/3324524

  6. vijay

    01.16.2011

    Hi.. My site could nt get the session.. all the time its saying “Sorry we could not authenticate you”.. I dont know wat to do..

  7. vijay

    01.16.2011

    Yippee.. i found the bug.. I hav given one AppId, App Secret in login module and another AppId, App Secret in callback module.. Hence the problem.. so it wont be confusing, if u follow the following pattern as Mufti Ali told earlier..
    in core.php
    Configure::write(‘Facebook.app_id’,’159813000xxxxx’);
    Configure::write(‘Facebook.app_secret’,’ad6caf36b2bfcc46cc867cxxxxxx’);

    in the controller you just call like this:
    $facebook=new Facebook(array(
    ‘appId’=>Configure::read(‘Facebook.app_id’),
    ‘secret’=>Configure::read(‘Facebook.app_secret’),
    ‘cookie’=>true
    ));

    Thanks to Mufti Ali…

    • Mufti Ali

      01.16.2011

      Congrat Vijay :D cheers..

  8. Mark

    01.21.2011

    Thanks! I had been trying to do this (albeit with codeigniter) but this gave me enough clues to crack it, thanks.
    Mark´s last blog ..Nexternal Review My ComLuv Profile

  9. Nattu

    02.12.2011

    Great work Mufti Ali. Good tutorial, Thank you.

  10. Bo-oz

    03.02.2011

    I think you would be better of extending the Auth module of Cakephp. Just read a good tutorial about it. You should really check it:

    http://cutfromthenorth.com/integrating-facebook-connect-with-cakephps-auth-component/

    This way you could handle both normal accounts and FB accounts at the same time!