A Complete Social Login Application Tutorial for CakePHP 2.3 (Twitter, Facebook and Google)

in CakePHP/PHP/Tutorials & Samples/Web Development

After writing the tutorial on how to create a complete login system using CakePHP, I have received a lot of requests for creating a tutorial on a social login system using CakePHP. Well, I’ve been real busy these days but I finally sat down to write the turorial… You can download it here and check out a live demo here. According to Wikipedia:

Social login, also known as social sign-in, is a form of single sign-on using existing login information from a social networking service such as Facebook, Twitter or Google+ to sign into a third party website in lieu of creating a new login account specifically for that website. It is designed to simplify logins for end users as well as provide more and more reliable demographic information to web developers

The following tutorial will show you how to integrate social login with CakePHP. This tutorial is an extension of the original complete login system using CakePHP. So, if you have not read this tutorial, please read it here. Below is a screenshot of what we are going to be creating and there is a live demo here.

cakephp-2_3-social-login-screenshot

Combining CakePHP’s Auth Component and Social Login

For anybody who has ever played with CakePHP’s Auth component, you probably already know the golden rule: CakePHP’s Auth component does not play nice with other authorization mechanisms. That is why most people who setup social login with CakePHP bypass the Auth component (which I personally think should never be done…) So, for this tutorial, we are going to build a system that allows members to either login using their social profile or by using the Auth component to create a username and password combination. In order to handle the social login aspect, I will be using the very popular HybridAuth PHP library. The actual protocol used for social login varies from provider to provider and the actual code for creating the login process is outside the scope of this tutorial. However, I will cover the top three social networks for social login: Facebook, Twitter and Google+. Before we start covering the actual steps of the tutorial, it is important to get your Social login credentials from the 3 providers mentioned above. Getting your social login API credentials for each of these social networks is explained below.

Social Authenticaion for Facebook

In order to be able to do social logins with Facebook, you need to obtain a key and a secret from Facebook. The following are the steps for getting your key and secret for Facebook

  1. Browse to https://developers.facebook.com/apps.
  2. Create an app, if you have not done so already. Set the "App Domain" as the domain name of your CakePHP site.
  3. Click on "Website with Facebook Login". set the site URL as the URL of your CakePHP site.
  4. Save this information somewhere for later use.

Social Authenticaion for Twitter

In order to be able to do social logins with Twitter, you need to obtain a key and a secret from Twitter. The following are the steps for getting your key and secret for Twitter

  1. Browse to https://dev.twitter.com/apps
  2. Create an application if you have not got one already. The most important thing for the application is the Callback URL which we will explain later when we begin the implementation.
  3. Save this information somewhere for later use.

Social Authenticaion for Google+

In order to be able to do social logins with Google+, you need to obtain a key and a secret from Google. The following are the steps for getting your key and secret for Google+:

  1. Browse to https://code.google.com/apis/console.
  2. Create a project, if you have not already.
  3. Click on API Access
  4. Create a client ID. You need to set the Redirect URI to http://example.com/auth_callback/google (replace example.com with your domain name. You can't use an invalid TLD, such as example.dev, for testing – Google does not allow this. you'll need to use dev.example.com instead, as well as your example.com live domain.)
  5. Save this information somewhere for later use.

The Setup

As mentioned earlier, we will be starting with the original CakePHP login app that was created in a previous tutorial. (You can download it here). Then we will be adding social login to this app. By adding a social login to our current login application, we want to provide users the ability to login to our CakePHP app via Facebook, Twitter, and/or Google. So the first thing we need to do is download the workhorse that will be taking care of the login: HybridAuth. HybridaAuth can be downloaded at http://hybridauth.sourceforge.net/download.html It is a very well-written and easy to use social login library written in PHP. Download the latest version of HybridAuth, unzip it and place the content in the app/Vendor directory. With that done, we are ready to modify our application to support social login.

Updating the Configuration Files

Now that we have obtained the key and the secret for the various social networks, we need to modify the core.php file to include information about the various social media providers. Although this tutorial is limited to Google+, Twitter and Facebook, HybridAuth allows you to use other networks such as LinkedIn, MySpace and Yahoo.

Core.php

So the following lines need to be added into core.php:

/** 
 * HybridAuth component
 *
 */
 Configure::write('Hybridauth', array(
    // openid providers
    "Google" => array(
        "enabled" => true,
        "keys" => array("id" => "Your-Google-Key","secret" => "Your-Google-Secret"),
    ),
	"Twitter" => array(
        "enabled" => true,
        "keys" => array("key" => "Your-Twitter-Key", "secret" => "Your-Twitter-Secret")
    ),
	"Facebook" => array(
        "enabled" => true,
        "keys" => array("id" => "Your-Facebook-Key", "secret" => "Your-Facebook-Secret"),
    ),
	"OpenID" => array(
        "enabled" => false
    ),
    "Yahoo" => array(
        "enabled" => false,
        "keys" => array("id" => "", "secret" => ""),
    ),
    "AOL" => array(
        "enabled" => false
    ),
    "Live" => array(
        "enabled" => false,
        "keys" => array("id" => "", "secret" => "")
    ),
    "MySpace" => array(
        "enabled" => false,
        "keys" => array("key" => "", "secret" => "")
    ),
    "LinkedIn" => array(
        "enabled" => false,
        "keys" => array("key" => "", "secret" => "")
    ),
    "Foursquare" => array(
        "enabled" => false,
        "keys" => array("id" => "", "secret" => "")
    ),
));

Note that you should replace the Your-Provider-Key and by Your-Provider-Secret with the actual values that you got from the various providers.

Routes.php

Routes.php must also be updated so that we create routes for the social login controllers. In the case of social login, two new routes are needed: social_login and social_endpoint whose functions will be discussed later.  Below are the 2 line changes needed in routes.php:

	Router::connect('/social_login/*', array( 'controller' => 'users', 'action' => 'social_login'));
	Router::connect('/social_endpoint/*', array( 'controller' => 'users', 'action' => 'social_endpoint'));

Updating the Models

At the model level, we will create a new model called SocialProfile. The SocialProfile object will be used to store social profile information. And as you can imagine, a social profile must belong to a user so the file SocialProfile.php will look like so:

App::uses('AuthComponent', 'Controller/Component');

class SocialProfile extends AppModel {
	
	public $belongsTo = 'User';

}

Now that we have a model called socialProfile, we need to associate it to the user model. To do so, we modify the Users model to indicate that it can have multiple social profiles. Here is the code that needs to be added:

	public $hasMany = array(
        'SocialProfile' => array(
            'className' => 'SocialProfile',
        )
    );

For now, the models are ready and we can begin to modify our controllers.

Creating A Component for HybridAuth

Instead of simply calling the HybridAuth library that we downloaded earlier, I have created a CakePHP Component called HybridAuthComponent. (I know the name is real original…). For those who have never played with components in CakePHP before, here is the definition of a component from the book:

Components are packages of logic that are shared between controllers

. This is exactly what we want: a reusable component that can be used from any controller. The component must be placed in the folder Controller/Component folder.

Analysis of the HybridAuth Component

The HybridAuth component will be the only component that interacts directly with the HybridAuth library. It loads HybridAuth from the Vendors folder and takes care of all the HybridAuth interactions. The functions of the component are all explained below:

Init()

This function is responsible for initializing the HybridAuth library. It also loads the key and secret settings that are defined in core.php for the various social providers. The other important thing that it does is define the endpoint. The endpoint is the link that the social networks redirect to after they have verified your key and secret. In this tutorial I set it to social_endpoint which is actually a rout for users/social_endpoint as we had previously defined in routes.php

processEndpoint()

In the world of social login, the endpoint is the proxy that connects your web application to the social network that you want to authenticate with. It is where the login tokens are exchanged between your application and the social network. The function processEndpoint is wrapper function for handling HybridAuth’s endpoint() function. All communication between the social network and your application happen through this function.

getSessionData() and restoreSessionData()

These 2 functions are one again wrapper functions for HybridAuth, this time for dealing with Session variables. HybridAuth usese Session values for authenticating.

Connect()

This function starts the process of connecting to a social network to start the social login process. Once again it is a wrapper function for HybridAuth. It takes one parameter known as $provider which a string that corresponds to the social network that you wish to connect to. For example “Google”, “Facebook” or “Twitter”. It also handles the various exceptions that could happen during the connection process.

normalizeSocialProfile()

This function’s primary role is to normalize the data coming from the various social networks. Keep in mind that not every social network sends the same information. For example, Twitter does not send first names, last names and email addresses. So this function handles these issues and finds a way to normalize the data. The most important thing to remember is that, if you add a new social network, chances are high that you may have to modify this function to fix any issues with the new social media that you add.

Below is the full code for the HybridAuth component

<?php

/**
 * CakePHP HybridauthComponent
 * @author mike
 */
class HybridauthComponent extends Component {

    public $hybridauth = null;
    public $adapter = null;
    public $user_profile = null;
    public $error = "no error so far";
    public $provider = null;
    public $debug_mode = false;
    public $debug_file = "";

    protected function init(){
        App::import('Vendor', 'hybridauth/Hybrid/Auth');
        $config = array(
            "base_url" => Router::url("/social_endpoint", true),
            "providers" => Configure::read('Hybridauth'),
            "debug_mode" => $this->debug_mode,
            "debug_file" => $this->debug_file,
        );
        $this->hybridauth = new Hybrid_Auth( $config );
    }
	
	/**
     * process the 
     * 
     * @return string
     */
    public function processEndpoint(){
        App::import('Vendor', 'hybridauth/Hybrid/Endpoint');
		
		if( !$this->hybridauth ) $this->init ();
        Hybrid_Endpoint::process();
    }
    
    /**
     * get serialized array of acctual Hybridauth from provider...
     * 
     * @return string
     */
    public function getSessionData(){
        if( !$this->hybridauth ) $this->init ();
        return $this->hybridauth->getSessionData();
    }
    
    /**
     * 
     * @param string $hybridauth_session_data pass a serialized array stored previously
     */
    public function restoreSessionData( $hybridauth_session_data ){
        if( !$this->hybridauth ) $this->init ();
        $hybridauth->restoreSessionData( $hybridauth_session_data );
    }
    
    /**
     * logs you out
     */
    public function logout(){
        if( !$this->hybridauth ) $this->init ();
        $providers = $this->hybridauth->getConnectedProviders();
        
        if( !empty( $providers ) ){
            foreach( $providers as $provider ){
                $adapter = $this->hybridauth->getAdapter($provider);
                $adapter->logout();
            }
        }
    }
    
    /**
     * connects to a provider
     * 
     * 
     * @param string $provider pass Google, Facebook etc...
     * @return boolean wether you have been logged in or not
     */
    public function connect($provider) {
        
        if( !$this->hybridauth ) $this->init ();
        
        $this->provider = $provider;

        try {
            
            // try to authenticate the selected $provider
            $this->adapter = $this->hybridauth->authenticate($this->provider);
            
            // grab the user profile
            $this->user_profile = $this->normalizeSocialProfile($provider);
            
            return true;
            
        } catch (Exception $e) {
            // Display the recived error
            switch ($e->getCode()) {
                case 0 : $this->error = "Unspecified error.";
                    break;
                case 1 : $this->error = "Hybriauth configuration error.";
                    break;
                case 2 : $this->error = "Provider [".$provider."] not properly configured.";
                    break;
                case 3 : $this->error =  "[" .$provider. "] is an unknown or disabled provider.";
                    break;
                case 4 : $this->error = "Missing provider application credentials for Provider [".$provider."].";
                    break;
                case 5 : $this->error = "Authentification failed. The user has canceled the authentication or the provider [" .$provider. "] refused the connection.";
                    break;
                case 6 : $this->error = "User profile request failed. Most likely the user is not connected to the provider [" .$provider. "] and he/she should try to authenticate again.";
                    $this->adapter->logout();
                    break;
                case 7 : $this->error = "User not connected to the provider [" .$provider. "].";
                    $this->adapter->logout();
                    break;
            }

            // well, basically your should not display this to the end user, just give him a hint and move on..
            if( $this->debug_mode ){
                $this->error .= "<br /><br /><b>Original error message:</b> " . $e->getMessage();
                $this->error .= "<hr /><pre>Trace:<br />" . $e->getTraceAsString() . "</pre>"; 
            }
            

            return false;
        }
    }
	
	/**
     * creates a social profile array based on the hybridauth profile object
     * 
     * 
     * @param string $provider the provider given from hybridauth
     * @return boolean wether you have been logged in or not
     */
	protected function normalizeSocialProfile($provider){
		// convert our object to an array
		$incomingProfile = (Array)$this->adapter->getUserProfile();
		
		// populate our social profile
		$socialProfile['SocialProfile']['social_network_name'] = $provider;
		$socialProfile['SocialProfile']['social_network_id'] = $incomingProfile['identifier'];
		$socialProfile['SocialProfile']['email'] = $incomingProfile['email'];
		$socialProfile['SocialProfile']['display_name'] = $incomingProfile['displayName'];
		$socialProfile['SocialProfile']['first_name'] = $incomingProfile['firstName'];
		$socialProfile['SocialProfile']['last_name'] = $incomingProfile['lastName'];
		$socialProfile['SocialProfile']['link'] = $incomingProfile['profileURL'];
		$socialProfile['SocialProfile']['picture'] = $incomingProfile['photoURL'];
		$socialProfile['SocialProfile']['created'] = date('Y-m-d h:i:s');
		$socialProfile['SocialProfile']['modified'] = date('Y-m-d h:i:s');
			
		// twitter does not provide email so we need to build someting
		if($provider == 'Twitter'){
			$names = explode(' ', $socialProfile['SocialProfile']['first_name']);
			$socialProfile['SocialProfile']['first_name'] = $names[0];
			$socialProfile['SocialProfile']['last_name'] = (count($names)>1 ? end($names) : '');
			$socialProfile['SocialProfile']['display_name'] = $socialProfile['SocialProfile']['first_name'] .'_'. $socialProfile['SocialProfile']['last_name'];
			$socialProfile['SocialProfile']['email'] = $socialProfile['SocialProfile']['display_name'] .'@Twitter.com';
		}
		
		return $socialProfile;
    }

}

Updating the Controllers

With the component ready, we can update the controllers. Before modifying the controllers, we need to modify the base file AppController by adding one line of code that is necessary for HybridAuth to work:

session_start();

This is required since HybridAuth requires this function to operate properly but CakePHP by default does not use it. With this done, we can modify the actual controllers. The only controller that we need to modify is the users controller. The first thing to do is create a dependency on the SocialProfile model. So we need to add the following line to indicate which models this controller uses:

	var $uses = array('User','SocialProfile');

Then we need to indicate that we will be using our newly created HybridAuthComponent. This is done with the following line of code:

	public $components = array('Hybridauth');

Finally, we need to modify the beforeFiler() function to tell the Auth component to allow 2 new functions to be available even if the user is not logged-in. There 2 functions are social_login and social_endpoint, which are covered later. Remember that these 2 functions are the same 2 functions that we created new routes for inside routes.php For now, here is how beforeFilter() now looks like:

    public function beforeFilter() {
        parent::beforeFilter();
        $this->Auth->allow('login','add','social_login','social_endpoint'); 
    }

Now we are ready to do the actual social login. Let’s start with the function social_login(). This function is used as the alternate way that users can login to the application. So the function login(), which already existed is left intact for users that want to use the usernema/password combination. And social_login() is created to handle all social logins. Below is the code for social_login()

	public function social_login($provider) {
		if( $this->Hybridauth->connect($provider) ){
			$this->_successfulHybridauth($provider,$this->Hybridauth->user_profile);
        }else{
            // error
			$this->Session->setFlash($this->Hybridauth->error);
			$this->redirect($this->Auth->loginAction);
        }
	}

This function is very simple: all it does is call HybridAuthCompoent with the $provider parameter. The $provider parameter is whichever provider that you wish to use for doing the actual social login. In this tutorial, it is limited to Facebook, Twitter or Google+, however it can be expanded to cover LinkedIn and other social networks. The function tells HybridAuth to try to connect using the provider that we specified. The credentials for that provider should have been placed inside your core.php configuration file under the HybridAuth section. If it is successful, we are redirected to the private function _successfulHybridauth(), if we fail, we are redirected to the login page with an error message.

If HybridaAuth is able to properly complete the social login, it will redirect to the function _successfulHybridauth(), which completes the actual login process and also informs the Auth component to let the user in. Remember that HybridAuth handles the authentication on the social network side and that CakePHP’s Auth component handles authentication on your application’s side. Here is what the function does:

  • It checks to see if the user has already authenticated into our application using the provided social network.
  • If a user has previously logged-in, then the user would have an entry inside the social profile table. So in this case, the social profile is already linked to a user and we simply have to retrieve the user and call the private function _doSocialLogin with the provided user.
  • If a user has never logged-in, we need to create a social profile for the user. But before doing so, we have to check to ensure that they are not currently logged-in using the traditional username and password combination.
    • If they are already logged-in, we create their social profile and let them know that their social profile is now linked to their account.
    • If they are not logged-in, then the user is logging into our system for the first time using their social profile. In this case, we need to create the user as well as their social profile. This is done in the user model with a function called: createFromSocialProfile. This function will be explained later but for the moment, you need to know that it will return a user object that can then be passed to the private function _ doSocialLogin.

Below is the full source code for _succesfulHybridauth:

	private function _successfulHybridauth($provider, $incomingProfile){

		// #1 - check if user already authenticated using this provider before
		$this->SocialProfile->recursive = -1;
		$existingProfile = $this->SocialProfile->find('first', array(
			'conditions' => array('social_network_id' => $incomingProfile['SocialProfile']['social_network_id'], 'social_network_name' => $provider)
		));
		
		if ($existingProfile) {
			// #2 - if an existing profile is available, then we set the user as connected and log them in
			$user = $this->User->find('first', array(
				'conditions' => array('id' => $existingProfile['SocialProfile']['user_id'])
			));
			
			$this->_doSocialLogin($user,true);
		} else {
			
			// New profile.
			if ($this->Auth->loggedIn()) {
				// user is already logged-in , attach profile to logged in user.
				// create social profile linked to current user
				$incomingProfile['SocialProfile']['user_id'] = $this->Auth->user('id');
				$this->SocialProfile->save($incomingProfile);
				
				$this->Session->setFlash('Your ' . $incomingProfile['SocialProfile']['social_network_name'] . ' account is now linked to your account.');
				$this->redirect($this->Auth->redirectUrl());

			} else {
				// no-one logged and no profile, must be a registration.
				$user = $this->User->createFromSocialProfile($incomingProfile);
				$incomingProfile['SocialProfile']['user_id'] = $user['User']['id'];
				$this->SocialProfile->save($incomingProfile);

				// log in with the newly created user
				$this->_doSocialLogin($user);
			}
		}	
	}

We have talked a few times about the private function _doSocialLogin so let’s look closely at this function. This is the most important function in the whole process because it is the function that tells CakePHP’s Auth component that the user has been authenticated. It takes in a parameter called $user. This parameter is super important since this is the user object that we will tell the Auth component to validate against. If Auth can validate the user, it will let the user through and you have successfully logged-in a social user, otherwise, Auth will block the user from accessing the restricted parts of the app. How can this all work? Well, its very simple: CakePHP’s Auth component has an alternative login function that takes as parameter the user object. That is why we need to pass the $user object to this function because it authenticates the user based on the user object instead of the traditional username and password combination. Below is the full code for the _doSocialLogin() function:

	private function _doSocialLogin($user, $returning = false) {

		if ($this->Auth->login($user['User'])) {
			if($returning){
				$this->Session->setFlash(__('Welcome back, '. $this->Auth->user('username')));
			} else {
				$this->Session->setFlash(__('Welcome to our community, '. $this->Auth->user('username')));
			}
			$this->redirect($this->Auth->loginRedirect);
			
		} else {
			$this->Session->setFlash(__('Unknown Error could not verify the user: '. $this->Auth->user('username')));
		}
	}

You are probably wondering what the optional flag $returning is for. Well, it’s just a fancy flag that allows you to change your message depending if the user is a returning visitor or a first time visitor. Remember that, in the function succesfulHybridauth(), we determine if the user is logging in for the first time or if they have logged-in already. So, we can then call _doSocialLogin() with this flag to indicate if it’s a returning visitor.

Updating the User Model to support First-Time social logins

The final part that we need to cover is the function in the user model that is responsible for creating the user from a given social profile. This is the function that I rightfully named: createFromSocialProfile(). This function basically creates a brand new user from a given social profile. Since the way we determine that a user is unique in our application is through their email address, this function checks to see if the email address is already in use or if a brand new user with the provided email address is required. The most important thing that this function does is map the user fields to the fields provided by the incoming social profile so that we have all basic information that we need to create a proper user that CakePHP’s Auth component can accept. At the end of it all, this function returns a user that can then be passed over to the _doSocialLogin() function.

	public function createFromSocialProfile($incomingProfile){
	
		// check to ensure that we are not using an email that already exists
		$existingUser = $this->find('first', array(
			'conditions' => array('email' => $incomingProfile['SocialProfile']['email'])));
		
		if($existingUser){
			// this email address is already associated to a member
			return $existingUser;
		}
		
		// brand new user
		$socialUser['User']['email'] = $incomingProfile['SocialProfile']['email'];
		$socialUser['User']['username'] = str_replace(' ', '_',$incomingProfile['SocialProfile']['display_name']);
		$socialUser['User']['role'] = 'bishop'; // by default all social logins will have a role of bishop
		$socialUser['User']['password'] = date('Y-m-d h:i:s'); // although it technically means nothing, we still need a password for social. setting it to something random like the current time..
		$socialUser['User']['created'] = date('Y-m-d h:i:s');
		$socialUser['User']['modified'] = date('Y-m-d h:i:s');
		
		// save and store our ID
		$this->save($socialUser);
		$socialUser['User']['id'] = $this->id;
		
		return $socialUser;
		
	
	}

Updating the Views

There is very little to modify at the views level other than the login.ctp file. We simply have to add the links to the social platforms and call the social_login function from the Users controller. This includes the links for Facebook, Twitter and Google+. For the purposes of this tutorial, I decided to use fancy images instead of boring text links. Here is what the links code looks like:

<?php
echo $this->Html->image("login-facebook.jpg", array(
    "alt" => "Signin with Facebook",
    'url' => array('action'=>'social_login', 'Facebook')
));

echo $this->Html->image("login-google.jpg", array(
    "alt" => "Signin with Google",
    'url' => array('action'=>'social_login', 'Google')
));

echo $this->Html->image("login-twitter.jpg", array(
    "alt" => "Signin with Twitter",
    'url' => array('action'=>'social_login', 'Twitter')
));
?>

And here is what they produce:

cakephp-2_3-social-login-screenshot

Final Notes

Although we have covered the social_login() function, the social_endpoint() function was never covered. That’s because it is simply a wrapper class for our HybridAuthComponent’s endpoint function. Remember that the endpoint is the one responsible for all interactions with the social network and that it is the URL that the social network will call when it needs information from our appliactoin. Below is the code for social_endpoint()

	public function social_endpoint($provider) {
		$this->Hybridauth->processEndpoint();
	}

The users controller’s logout function must also be modified so that it calls our HybridAuthComponent’s logout function as well. This function now looks like so:

	public function logout() {
		$this->Hybridauth->logout();
		$this->redirect($this->Auth->logout());
	}

Download it all

That’s all there is to being able to login to a CakePHP App using social login.  You can download the entire tutorial in zip format here.

Tags:

Mifty Yusuf is a Montreal-based software developer who enjoys playing with new web technologies as well as comic books and illustrations. He beleives that, no matter what the question is, the answer is always Batman!

125 Comments

  1. Fatal Error

    Error: Call to a member function connect() on null
    File: ……….app\Controller\UsersController.php
    Line: 491

    Notice: If you want to customize this error message, create app\View\Errors\fatal_error.ctp

    hello sir i got the above error please help me!

  2. Hello I have a strange error : “Serialization of ‘Closure’ is not allowed

    Never happened to anyone ‘?

    Thanks

    Rudy

  3. hi,
    i have this error on connect with facebook.

    Warning (2): Missing argument 1 for UsersController::social_endpoint() [APP/Controller/UsersController.php, line 62]

    Can you help me .

  4. Hi Mifty,
    Thanks a lot for this wonderful tutorial and code.

    Ive implemented your code in my project but im getting this error:

    Warning (2): Missing argument 1 for UsersController::social_endpoint() [APP/Controller/UsersController.php, line 386]
    Warning (2): Cannot modify header information – headers already sent by (output started at /**************************/lib/Cake/Utility/Debugger.php:765)

    Please help.

    Thanks again.

    • Hello Chris,
      This error usually happens if you are printing some value before your view is rendered. do you have something being printed?

    • Hi Chris,
      I was able to reproduce the problem with debugging on. Its my bad. I forgot to add a default value for the $provider parameter for the social_endpoint() function. It has been fixed with the latest zip package and the function now looks like so:

      	public function social_endpoint($provider = null) {
      		$this->Hybridauth->processEndpoint();
      	}
      

      Thanks for pointing out the error and it is now fixed.

      • Hi Mifty, many thanks for the fix.
        It works fine however i ran into problems when i used it on another project thats authenticates via an api call (found in ApiServiceComponent which works fine with normal auth)
        How can i get hybridauth to use a different authenticate.
        On my project in the before filter i have:

        $this->Auth->loginRedirect = array(‘controller’ => ‘users’, ‘action’ => ‘index’);
        $this->Auth->logoutRedirect = array(‘controller’ => ‘homes’, ‘action’ => ‘index’);
        $this->Auth->authError = ‘Access denied – You must be logged in to continue.’;
        $this->Auth->authenticate = array(‘ApiService’);
        $this->Auth->authorize = array(‘Controller’);

        also in the database, I have no fields for ‘username’, ‘role’ & ‘status’.
        and i wish to use db field ’email’ in place of ‘username’ .

        Thanks,

        Chris

  5. Seems to be too good to be true this tutorial 🙂 Also getting the Missing Argument error, probably because Im using a newer Cake release (2.6.0). Will now try it with cake 2.3.0

    • Also with cake 2.3.0 this happens. I’m running the app as I downloaded here and it gives:
      Warning (2): Missing argument 1 for UsersController::social_endpoint() [APP/Controller/UsersController.php, line 18]
      when you click on a logo (Ive tried both Facebook and Google)

      • Thanks for the update Tim. i’ll download the zip package on a test server and try it out this weekend. If I find any issues, I’ll correct it and post an update to this thread

  6. Hi there,

    Just mentioning that I will be trying out this tutorial for Cakephp 3.0 (not sure what the differences are in the steps). Also will be attempting to somehow allow my phonegap application to talk via REST to my cakephp 3.0 application to perform social login. Anyone have experience doing something similar, and can share some pointers in advance? Very much appreciated!

    Kevin

    • Hi Kevin,
      This piece of code will have to be modified to support Cakephp 3.0. There are many new concepts that are introduced in CakePHP 3.0 that are different fom 2.x.

    • Hi Tim,
      I was able to reproduce the problem with debugging on. Its my bad. I forgot to add a default value for the $provider parameter for the social_endpoint() function. It has been fixed with the latest zip package and the function now looks like so:

      	public function social_endpoint($provider = null) {
      		$this->Hybridauth->processEndpoint();
      	}
      

      Thanks for pointing out the error and it is now fixed.

  7. Table social_profiles for model SocialProfile was not found in datasource default.

    i get this error when i add a user .also the login with facebook returns

    Class ‘Hybrid_Auth’ not found

    please help.

    • Please verify that you are loading the class into the correct directory relative to the vendor folder.
      In my case:

      Before: App::import(‘Vendor’, ‘hybridauth/Hybrid/Auth’);

      After: App::import(‘Vendor’, ‘hybridauth/hybridauth/Hybrid/Auth’);

  8. Hello Mifty,

    Thanks for the tutorial, but i got an error of redirect_uri_mismatch. what can be the cause for this problem.

    Waiting for your reply

  9. Hi Mifty!
    This is a superb article. i have searched alot about integration of social login in existing login. And you Know what i was bored because i could not get any topic untill i reched at your site. After reading your tautorial i am no longer bored. Yeah mifty you are my man bro………
    Keep it up man i m not gona leave your site now…..

  10. Hi Mifty!
    I was running the application on localhost. Every thing was running perfectly. but when i allowed my app to take info from facebook it has not redirect me to index function. and gave me an error that socialprofiles table not found in datasource default.
    i did not get this one because we are saving the data in users table and also we difine dependency of user on socialprofile…… it’s kind of confusing to me kindly elaborate it please……..

    • hey Zubair,
      Can you please send me the source code ?
      I am facing the problem that when i click on login with facebook ,it gives me the same error.
      Also adding a new user also gives an error.
      Please help.

      • Hi Raj!
        There is nothing to worry about it. you just go to phpmyadmin and create a table of socialprofiles.
        make its fields that are mentioned in normalizesocialprofile function in hybridauth component file.
        Or If you want to learn deeply just read the whole code line by line.

        • Hey.Thanks it worked.
          BUt when i click on Login with Facebook i am redirected to

          localhost/social_endpoint?hauth.start=Facebook&hauth.time=1434451048

          and it shows :HybridAuth
          Open Source Social Sign On PHP Library.
          hybridauth.sourceforge.net/

          Kindly help.

          • hey raj!
            I am facing the same error while trying to login through google plus. I have searched it alot and what i found is that the redirect url registered at api is wrong. but still thats not working… Hope fully Sir Mifty can help regarding this.

          • Hi Zubair. In the case of Google Plus, you cannot use your localhost to test social login. You must be on an actual live server that Google can communicate with (They need to verify the URI and confirm that it is valid on their end). When you use localhost or a local dev environment, Google cannot verify and that is why it fails with Google Plus. Hope this helps

          • Hi Mifty Sir ! I make it worked at localhost in the case of google plus. the problem was that social_endpoint requests to google plus to some other url and the redirect url was something else. I copied the social end point url from error and pasted it in redirect url field at google plus configuration site. and it worked. Thats What i got.

            Now i am using social login with twitter but there are some errors. i do not know what but here they are

            Undefined index: oauth_token [APP/Vendor/hybridauth/Hybrid/thirdparty/OAuth/OAuth1Client.php, line 85]
            Cannot modify header information – headers already sent by (output started at /var/www/doobie_x/lib/Cake/Utility/Debugger.php:801) [APP/Vendor/hybridauth/Hybrid/Auth.php, line 354]

            Kindly take a look at these and guide me.
            Waiting for your reply Sir.

  11. Hi Mifty!
    This is a superb article. i have searched alot about integration of social login in existing login. And you Know what i was bored because i could not get any topic untill i reched at your site. After reading your tautorial i am no longer bored. Yeah mifty you are my man bro………
    Keep it up man i m not gona leave your site now…..
    I was running the application on localhost. Every thing was running perfectly. but when i allowed my app to take info from facebook it has not redirect me to index function. and gave me an error that socialprofiles table not found in datasource default.
    i did not get this one because we are saving the data in users table and also we difine dependency of user on socialprofile…… it’s kind of confusing to me kindly elaborate it please……..

    • the purpose of the socialprofile table is to associate a user to multiple social profiles. Imagine that I have a twitter profile, a facebook profile and a Google profile. In this case, there will be 3 social profile entries for my username. One for each social network

        • Hey,
          Mifty sir can you please help me with facebook login?
          When i click on Login with Facebook i am redirected to

          localhost/social_endpoint?hauth.start=Facebook&hauth.time=1434451048

          and it shows :HybridAuth
          Open Source Social Sign On PHP Library.
          hybridauth.sourceforge.net/

          I think i am having problem in registering with facebook.

          Kindly help.

  12. Hi ,
    Mifty

    Thanks for you code you have provided Login with Facebook account. Great Work man really.
    Thanks a lot for your efforts

    But

    I have a problem. I followed all the steps as you told in your code .
    I have created the data base as well .
    But when i clicked on the Facebook login button it gives me the error.

    ======================================================
    Invalid Scopes: offline_access, publish_stream, read_friendlists. This message is only shown to developers. Users of your app will ignore these permissions if present. Please read the documentation for valid permissions at: https://developers.facebook.com/docs/facebook-login/permissions
    =======================================================

    Please help me man its urgent. Please Please Please……….

    Thanks in advance

    • You need to change hybridauth/hybridauth/Hybrid/Providers/Facebook.php file.

      Change the scope to this – public $scope = “email, user_hometown”; //add other scopes if you need.

  13. Hi Sir Mifty !
    In case of social login with twitter. I debug the error and what i found is that curl is necessary for 0auth library.
    But problem is that i m on ubuntu i installed curl and for one time the whole code work. even an entry was there in database. But after some time same problem was occuring. ireinstall curl and whole php, apache but still the same error existed.
    kindly tell me something because i am stuck and feeling tired at this task.
    please help please please please…………

  14. Hi Mifty!
    Man Your code is very good. I have tried it.It worked well with the facebook.
    But i am facing an issue when i try to login using google plus using your code & it
    gives an error saying this
    “User profile request failed. Most likely the user is not connected to the provider [Google] and he/she should try to authenticate again.”
    I have tried many things but could’nt solve this.The error is still confusing me.
    Plz help…..

  15. After login using Hybrid Auth Why #_=_ Append at last of url .Is there any way to remove it from url

    Thanks Aloat your stuff is working for me bro u are great

  16. Great stuff. I tried with my CakePHP website. The authentication with Facebook and Twitter worked, but after the authentication it should have created a new user. But I get this error:

    Notice (8): Array to string conversion [CORE/Cake/Model/Datasource/DboSource.php, line 460]

    Don’t know why.
    And with Google +, it doesn’t even authenticate. It just gives me this error: Error: redirect_uri_mismatch
    This one apparently is just a app configuration error on my part, but if you know how to solve this, please help.

    Anyone?

    • Well… I solved the Google + redirect problem.

      But, now I’m getting the: Notice (8): Array to string conversion [CORE/Cake/Model/Datasource/DboSource.php, line 460]
      From all three of them. Apparently the login works, but the system doesn’t seem to be able to save the user.
      The Stack Trace is:

      Database Error
      Error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘createFromSocialProfile’ at line 1

      SQL Query: createFromSocialProfile

      Notice: If you want to customize this error message, create app/View/Errors/pdo_error.ctp

      Stack Trace
      CORE/Cake/Model/Datasource/DboSource.php line 460 → PDOStatement->execute(array)
      CORE/Cake/Model/Datasource/DboSource.php line 426 → DboSource->_execute(string, array)
      CORE/Cake/Model/Datasource/DboSource.php line 668 → DboSource->execute(string, array, array)
      CORE/Cake/Model/Datasource/DboSource.php line 611 → DboSource->fetchAll(string, array, array)
      CORE/Cake/Model/Model.php line 827 → DboSource->query(string, array, User)
      APP/Controller/UsersController.php line 164 → Model->__call(string, array)
      APP/Controller/UsersController.php line 164 → User->createFromSocialProfile(array)
      APP/Controller/UsersController.php line 127 → UsersController->_successfulHybridauth(string, array)
      [internal function] → UsersController->social_login(string)
      CORE/Cake/Controller/Controller.php line 490 → ReflectionMethod->invokeArgs(UsersController, array)
      CORE/Cake/Routing/Dispatcher.php line 193 → Controller->invokeAction(CakeRequest)
      CORE/Cake/Routing/Dispatcher.php line 167 → Dispatcher->_invoke(UsersController, CakeRequest)
      APP/webroot/index.php line 118 → Dispatcher->dispatch(CakeRequest, CakeResponse)

      • i am also getting the same error right after i solved my redirection issue with google+ LOGIN..
        any help will be appreciated.
        Thank you.

    • Hello everyone, and thank you Mifty for sharing this very useful component.
      Danie, I’m also facing an issue with the redirection url.
      Could you please share your solution ?
      Best

  17. Thank you very much for this tutorial, I get the following error: “Unknown Error Could not verify the user” and also certain fields of the social profile table are not filled fields like user_id, first name, name laste link, it is due to what?
    Thank you

  18. suppose we deactived any user from back end and then user login in my site through facebook or google+,since the account is inactive I need to show msg as”Inactive account” as we can show for normal login .

  19. Hey Mifty,

    Great tutorial, thank you. However, unfortunately I’m running into an issue. When a new user logs in for the first time with either Facebook, Google, or Twitter; a new User is created in our User table, and also a new Social Profile is created in our social profile table. However, after they have successfully gone through the login process for the first time, we get the error below when attempting to re-login with either Facebook, Twitter or Google for the second time.

    Any suggestions on whats triggering this?

    Thanks!

    Error: SQLSTATE[23000]: Integrity constraint violation: 1052 Column ‘id’ in where clause is ambiguous

    SQL Query: SELECT `User`.`id`, `User`.`oauth_provider`, `User`.`oauth_uid`, `User`.`access_token`, `User`.`username`, `User`.`password`, `User`.`email`, `User`.`firstname`, `User`.`lastname`, `User`.`group_id`, `User`.`role`, `User`.`status`, `User`.`created`, `User`.`modified`, `Group`.`id`, `Group`.`name`, `Group`.`parent_id` FROM `menslifestyles`.`ml_users` AS `User` LEFT JOIN `menslifestyles`.`ml_groups` AS `Group` ON (`User`.`group_id` = `Group`.`id`) WHERE `id` = 34 ORDER BY `User`.`username` ASC LIMIT 1

    Notice: If you want to customize this error message, create app/View/Errors/pdo_error.ctp

    Stack Trace
    CORE/Cake/Model/Datasource/DboSource.php line 458 → PDOStatement->execute(array)
    CORE/Cake/Model/Datasource/DboSource.php line 424 → DboSource->_execute(string, array)
    CORE/Cake/Model/Datasource/DboSource.php line 665 → DboSource->execute(string, array, array)
    CORE/Cake/Model/Datasource/DboSource.php line 1077 → DboSource->fetchAll(string, boolean)
    CORE/Cake/Model/Model.php line 2903 → DboSource->read(User, array)
    CORE/Cake/Model/Model.php line 2875 → Model->_readDataSource(string, array)
    APP/Controller/UsersController.php line 329 → Model->find(string, array)
    APP/Controller/UsersController.php line 305 → UsersController->_successfulHybridauth(string, array)
    [internal function] → UsersController->social_login(string)
    CORE/Cake/Controller/Controller.php line 490 → ReflectionMethod->invokeArgs(UsersController, array)
    CORE/Cake/Routing/Dispatcher.php line 185 → Controller->invokeAction(CakeRequest)
    CORE/Cake/Routing/Dispatcher.php line 160 → Dispatcher->_invoke(UsersController, CakeRequest, CakeResponse)
    APP/webroot/index.php line 108 → Dispatcher->dispatch(CakeRequest, CakeResponse)

  20. suppose we deactived any user from back end and then user login in my site through facebook or google+,since the account is inactive I need to show msg as”Inactive account” as we can show for normal login .please let know changes in auth or user files needed.

Leave a Reply

Your email address will not be published.

*

Latest from CakePHP

Go to Top