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).
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.
Go to website tab, fill Site URL with your application url, for axample http://localhost/fboauth?.
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:
- cakephp facebook login
- cakephp facebook sdk
- cakePHP facebook authentication
- facebook login cakephp
- How to Authenticate Users With Facebook Connect
- cakephp facebook graph api
- cakephp facebook oauth
- cakephp facebook
- cakephp login with facebook
- cakephp facebook redirecting the request for this address in a way that will never complet
15 Comments
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
));
Amol Deshpande
11.13.2010
Hi, Thanks a lot for these steps. It help me out of my problem.
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
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);
}
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”.
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
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..
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
cheers..
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
Nattu
02.12.2011
Great work Mufti Ali. Good tutorial, Thank you.
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!
There are no trackbacks to display at this time.