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. Notice (1024): Element Not Found: Elements/default.ctp [CORE/Cake/View/View.php, line 425]

    Error: The view for UsersController::social_login() was not found.

    Stack Trace
    CORE/Cake/View/View.php line 470 → View->_getViewFileName(null)
    CORE/Cake/Controller/Controller.php line 960 → View->render(null, null)
    CORE/Cake/Routing/Dispatcher.php line 200 → Controller->render()
    CORE/Cake/Routing/Dispatcher.php line 167 → Dispatcher->_invoke(UsersController, CakeRequest)
    APP/webroot/index.php line 111 → Dispatcher->dispatch(CakeRequest, CakeResponse)

  2. Hi,

    When we are trying to login using FB at that time one copy of data was not saved in users table and because of that when i try to login again using FB it gives me error with blank $user array.

    Can you please help me to sort out this issue.

    Thanks,

  3. Hi Mifty i tried to implement the code which u have publish but if iam trying to login with social ids iam getting error as Invalid App ID: Your-Facebook-Key same for google+ also

  4. My Callback url gives error when i cancel login from google and twitter. Please help, i didn’t find any proper solutions for this.

    Error message is “Authentication failed! Twitter returned an invalid oauth verifier.”;

  5. Hi Mifty, I have been trying to get this code working the last week or so. Google and Facebook worked almost rightaway but Twitter gave me some hassle. The first login with Twitter worked OK but the second time threw errors. I just found out what caused this behaviour so I thought I could help other users.
    In the HybridAuthComponent, the normalizeSocialProfile() method makes up a placeholder emailaddress for the incoming Twitter user. This emailaddress was stored in the social_profiles table but not in the users table. It turns out that the placeholder emailaddress was not accepted in the validation rules in the User Model so the save() action in the createFromSocialProfile() method didn’t work.
    I removed the ‘alphaNumericDashUnderscore’ rule for username in the User Model and I changed the underscore to a dot in the creation of display_name in the normalizeSocialProfile method of the HybridAuthComponent. After these changes, the incoming Twitter user was saved in the user table and Twitter authentication worked fine.

    Cheers,

    Erik.

    • Hi Erik,
      Thanks for sharing your experience and letting others know how it worked out for you. I am a bit surprised that you had to remove the method alphaNumericDashUnderscore. I am using it on the live demo that i have up and running on this blog. Anyways, I’m glad you were able to make it work.

  6. Hi,
    When we are trying to login using FB i found error like ” You are not logged in: You are not logged in. Please log in and try again.”

    i cant understand what can i do????????????? i am putting all thing that have you told please suggest

    Thanks

    • you are mostly likely not logged-in to facebook or you are logged-in to facebook but as a page instead of your regular profile. If thats the case, all you have to do is switch from page profile to your normal profile and you should be fine

  7. Thank you so much, i have setup successfuly.
    everything is ok…. but afterfter login, my page redirect to index, but have some character “#_=_” on address i dont know why

    ex. mysite.com/#_=_

    —–
    my AppcontrollerAppcontroller
    redirect in my auth is ‘loginRedirect’ => ‘/’,
    please help me! sorry my english

  8. Hi,

    My code is working fine with Google+ but it is giving problem with twitter and facebook.
    For twitter its giving:
    Warning (2): Missing argument 1 for UsersController::social_endpoint() [APP/Controller/UsersController.php, line 83]
    Notice (8): Undefined index: oauth_token [APP/Vendor/hybridauth/Hybrid/thirdparty/OAuth/OAuth1Client.php, line 85]
    Notice (8): Undefined index: oauth_token_secret [APP/Vendor/hybridauth/Hybrid/thirdparty/OAuth/OAuth1Client.php, line 85]
    Warning (2): Cannot modify header information – headers already sent by (output started at /var/www/html/cakephpProjects/reelie/lib/Cake/Utility/Debugger.php:801) [APP/Vendor/hybridauth/Hybrid/Auth.php, line 363]

    For facebook:
    Given URL is not permitted by the Application configuration: One or more of the given URLs is not permitted by the App’s settings. It must match the Website URL or Canvas URL, or the domain must be a subdomain of one of the App’s domains.

    But my apps setting is totally fine. Please guide on this.
    Thank you.

    • Hi,

      Your tutorial is really very helpful.Thanks for sharing.
      Its working for Google and Twitter. But still no luck for facebook.
      I have tried so much. But it is giving error like –
      “You are not logged in: You are not logged in. Please log in and try again.”

      I have checked all settings. But I am not getting any solution for facebook. I appreciate if I can get reply soon.
      Thank you in advance.

  9. i have successfully integrated for twitter,google but for Facebook I am having issue.
    Error:
    Given URL is not permitted by the Application configuration: One or more of the given URLs is not permitted by the App’s settings. It must match the Website URL or Canvas URL, or the domain must be a sub domain of one of the App’s domains.

    My apps setting and coding settings for URL are correct. but I am not getting solution. Please guide on this.

    Thanks in advance

  10. HI,
    I am facing login redirect issue on a server, when i am login with facebook then after that it will redirect to blank page

    please suggest, it’s urgent

  11. Hello Mifty, first, i’d like to thank you for this tutorial.
    I’m trying to follow it but i’m facing an issue.
    The social profile is saving on table but nothing in user table. Have you an idea about how to proceed? sorry for my english

  12. Thanks this fucking awesome contribution. I’m facing the 400 error on google+ The url needs to be verified? I can’t figure out why, but I did this and I can’t add the domain before validated. any glue?

  13. hello

    i m trying your code but i got an error in login with google…

    Error: redirect_uri_mismatch
    please help to solve this
    please

  14. Hi Mifty
    i have replaced app folder from your app folder in my test application. Its successfully redirecting me to facebook login page but after putting facebook username and password getting error “Authentication failed! Facebook returned an invalid user id”. Please tell me what’s going wrong

    • this mostly happens when you have not registered your return URL on your facebook app. SO, for example, your using a.com as your return domain in the facebook app but you are actually testing from b.com which is not recognized by facebook.

  15. hi Mifty I am trying to login with facebook but after i click login with facebook button it says something like this :
    ” Sorry, something went wrong.

    We’re working on getting this fixed as soon as we can.

    Go Back ”
    please some help ?

  16. Mifty, This one + your admin routing tutorials = very good stuff! By trade I’m a boring DBA but I dabble with web stuff in my spare time. Thanks to you I crash coursed on cakephp 2.x and was able to get a working cakephp site with social login and dropbox integration (cakebox [+ couple hacks]).

  17. hi Mifty..

    i have a problem…when i click facebook button it shows that Hybrid_auth class not found in Hybridauth component…please help me..

    • Hi Samanta. Unfortunately, I no longer maintain this tutorial because CakePHP 2.3 is pretty old. Have you tried upgrading to Laravel or Cake 3.0?

Leave a Reply

Your email address will not be published.

*

Latest from CakePHP

Go to Top