Yii 1.1: Integrating HybridAuth directly into Yii without an extension

17 followers

This article tries to explain the steps required in integrating the HybridAuth into Yii directly, without using an extension.

The reason for not using an existing extension, such as hoauth is because the extension assumes a pre-defined database table structure to be used. An application i am developing, already had the direct login system implemented (where the user enters his/her email and password for signing-in or signing-up.) Now i had to integrate the social login feature into the existing system. Also, i required the flexibility that the user can login once through their Google Account, next time through their Facebook account, yet another time through LinkedIn etc.

Lets assume a login html similar to the example shown in the HybridAuth documentation link: http://hybridauth.sourceforge.net/userguide/Integrating_HybridAuth_Social_Login.html

I am going to use different actions within the SiteController for:

  1. Logging through the traditional system of username(email)/password (through a 'signIn' action)
  2. Social Login (through a 'login' action)

This is just for making the tutorial easy, and trying to have different functions for different user actions. You can choose to implement both these options in the same action.

The html for traditional login would be something like this:

<form action="signIn" method="post"> 
    <fieldset>
        <legend>Sign-in form</legend>
        login   : <input type="text" name="login" /><br /> 
        password: <input type="password" name="password" /><br /> 
 
        <input type="submit" value="Sign-in" />
    <fieldset>
</form>

The html for Social Login could be:

<div> 
    <a href="login.php?provider=google"><img src="images/buttons/google.png" /></a>
    <br/>
    <a href="login.php?provider=facebook" ><img src="images/buttons/facebook.png"  /></a>
    <br/>
    <a href="login.php?provider=linkedin"><img src="images/buttons/linkedin.png" /></a>
    <br/>
    <a href="login.php?provider=yahoo"><img src="images/buttons/yahoo.png" /></a>
    <br/>
    <a href="login.php?provider=live"><img src="images/buttons/live.png" /></a>
</div>

I am going to concentrate only on actionLogin() and not actionSignIn().

Initial Setup of HybridAuth

  1. Download the latest version of HybridAuth (version 2.1.2 as of this writing) from the link: http://hybridauth.sourceforge.net/download.html#index
  2. Extract the contents to some folder in your application, lets say the extensions folder.
  3. Create a php file named HybridAuthIdentity, in the components folder. This class extends from the CUserIdentity class. (Note that this is not very important. I am just trying to show the way i have done it).
  4. The overall directory structure assumed in this tutorial is:
/*numbers indicate the folder or file depth*/
 1 components
   2 HybridAuthIdentity

 1 controllers
   2 SiteController

 1 extensions
   2 HybridAuth
     3 hybridauth-2.1.2
       4 hybridauth
         5 index.php
         5 Hybrid
           6 Auth.php

HybridAuthIdentity Constructor

This new class has the following initial code:

class HybridAuthIdentity extends CUserIdentity
{
    const VERSION = '2.1.2';
 
    /**
     * 
     * @var Hybrid_Auth
     */
    public $hybridAuth;
 
    /**
     * 
     * @var Hybrid_Provider_Adapter
     */
    public $adapter;
 
    /**
     * 
     * @var Hybrid_User_Profile
     */
    public $userProfile;
 
    public $allowedProviders = array('google', 'facebook', 'linkedin', 'yahoo', 'live',);
 
    protected $config;
 
    function __construct() 
    {
        $path = Yii::getPathOfAlias('ext.HybridAuth');
        require_once $path . '/hybridauth-' . self::VERSION . '/hybridauth/Hybrid/Auth.php';  //path to the Auth php file within HybridAuth folder
 
        $this->config = array(
            "base_url" => "https://mysite.com/site/socialLogin", 
 
            "providers" => array(
                "Google" => array(
                    "enabled" => true,
                    "keys" => array(
                        "id" => "google client id", 
                        "secret" => "google secret",
                    ),
                    "scope" => "https://www.googleapis.com/auth/userinfo.profile " . "https://www.googleapis.com/auth/userinfo.email",
                    "access_type" => "online",
                ),  
                "Facebook" => array (
                   "enabled" => true,
                   "keys" => array ( 
                       "id" => "facebook client id", 
                       "secret" => "facebook secret",
                   ),
                   "scope" => "email"
                ),
                "Live" => array (
                   "enabled" => true,
                   "keys" => array ( 
                       "id" => "windows client id", 
                       "secret" => "Windows Live secret",
                   ),
                   "scope" => "email"
                ),
                "Yahoo" => array(
                   "enabled" => true,
                   "keys" => array ( 
                       "key" => "yahoo client id", 
                       "secret" => "yahoo secret",
                   ),
                ),
                "LinkedIn" => array(
                   "enabled" => true,
                   "keys" => array ( 
                       "key" => "linkedin client id", 
                       "secret" => "linkedin secret",
                   ),
                ),
            ),
 
            "debug_mode" => false, 
 
            // to enable logging, set 'debug_mode' to true, then provide here a path of a writable file 
            "debug_file" => "",             
        );
 
        $this->hybridAuth = new Hybrid_Auth($this->config);
    }
 
    /**
     *
     * @param string $provider
     * @return bool 
     */
    public function validateProviderName($provider)
    {
        if (!is_string($provider))
            return false;
        if (!in_array($provider, $this->allowedProviders))
            return false;
 
        return true;
    }
 
}

Within the constructor the following steps occur:

  1. Import the Auth.php file
  2. Set the configuration parameters (in this tutorial, the configuration for HybridAuth is stored within the HybridAuthIdentity class, and there is no need for a seperate config.php file. Notice the 'base_url' address in the config parameters. The url points to a 'socialLogin' action in SiteController, which would be created in sometime.
  3. Create a new Hybrid_Auth object.

The '$allowedProviders' property is used for validation purpose.

Note: For Google/Facebook/Live, your client id is represent by the id parameter within the keys subarray, but for LinkedIn and Yahoo, the same is represented by key parameter

For Yahoo, if the above do not work, try including your application id in the configuration:

"Yahoo" => array(
    "enabled" => true,
    "keys" => array ( 
        "id" => "your yahoo application id",    //the additional parameter
        "key" => "yahoo consumer id", 
        "secret" => "yahoo secret",
    ),
),

SiteController actions

Two actions are required in this controllers:

  1. One for the login action, when the user clicks a particular provider image.
  2. Second is the 'socialLogin' action that has been mentioned as the url for HybridAuth config.

Step 1: actionLogin():

//action only for the login from third-party authentication providers, such as Google, Facebook etc. Not for direct login using username/password
    public function actionLogin()
    {
        if (!isset($_GET['provider']))
        {
            $this->redirect('/site/index');
            return;
        }
 
        try
        {
            Yii::import('ext.components.HybridAuthIdentity');
            $haComp = new HybridAuthIdentity();
            if (!$haComp->validateProviderName($_GET['provider']))
                throw new CHttpException ('500', 'Invalid Action. Please try again.');
 
            $haComp->adapter = $haComp->hybridAuth->authenticate($_GET['provider']);
            $haComp->userProfile = $haComp->adapter->getUserProfile();
 
            $haComp->processLogin();  //further action based on successful login or re-direct user to the required url
        }
        catch (Exception $e)
        {
            //process error message as required or as mentioned in the HybridAuth 'Simple Sign-in script' documentation
            $this->redirect('/site/index');
            return;
        }
    }

Explanation of the actionLogin() function:

  1. Check if the $_GET['provider'] parameter was received from the client. If not, redirect the user as required.
  2. Import the HybridAuthIdentity class (if the components folder is not defined to be auto-imported).
  3. Validate the $_GET['provider'] parameter to confirm that the provider name is within the list of allowed providers.
  4. The next two lines, initializing the adapter and userProfile, are lifted directly from HybridAuth. For explanation refer to the HybridAuth documentation.

Step 2: actionSocialLogin():

public function actionSocialLogin()
    {
        Yii::import('ext.components.HybridAuthIdentity');
        $path = Yii::getPathOfAlias('ext.HybridAuth');
        require_once $path . '/hybridauth-' . HybridAuthIdentity::VERSION . '/hybridauth/index.php';
 
    }

Explanation: This action just requires importing of the index.php file of HybridAuth.

Registering with the Service Providers:

For registering with the service providers, mention the Callback Url as 'https://mysite.com/site/socialLogin?hauth.done=providerName'

Replace providerName with the actual provider name. Example callback URLs:

  1. https://mysite.com/site/socialLogin?hauth.done=Google
  2. https://mysite.com/site/socialLogin?hauth.done=Facebook
  3. https://mysite.com/site/socialLogin?hauth.done=LinkedIn
  4. https://mysite.com/site/socialLogin?hauth.done=Yahoo
  5. https://mysite.com/ - for Windows Live (just the full domain name is enough. Live does not accept query string in its redirect URL)

Note: With this setup process, the install method mentioned in the HybridAuth documentation need not be executed. But remember to delete the install.php file (with or without executing it).

Logging into the Yii Authentication Framework

After the authentication, the code for redirecting the user to the logged in section is completely as per individual requirements.

At the minimum, you can login the user into Yii:

//goes into HybridAuthIdentity class
 
    public function login()
    {
        $this->username = $this->userProfile->email;  //CUserIdentity
        Yii::app()->user->login($this, 0);
    }
 
    public function authenticate() 
    {
        return true;
    }

The authenticate() code simply returns true unconditionally. Call the login() function after authentication in actionLogin() of SiteController and then redirect the user to the user module/controller.

public function actionLogin()
    {
            :
            :
            $haComp->adapter = $haComp->hybridAuth->authenticate($_GET['provider']);
            $haComp->userProfile = $haComp->adapter->getUserProfile();
 
            $haComp->login();
            $this->redirect('');  //redirect to the user logged in section..
    }

Any suggestions to further improve the code or the wiki are welcome.

Total 7 comments

#17723 report it
Ankit Modi at 2014/07/17 08:38am
Query

Hi,

It's should be return image and all profile without password?

When I use I get the error

got an error! Authentication failed! Facebook returned an invalid user id.

How to solved it?

#15805 report it
Shahir Reza Ali at 2013/12/19 12:00am
failed to open stream: No such file or directory

i was getting an error every time i clicked on my login link (using Yii v1.1.14 and HybridAuth v 2.1.2)

<a href="http://mysite/login?provider=facebook" >facbeook login</a>

The error message was...

include(/Applications/XAMPP/xamppfiles/htdocs/dev/protected/extensions/components/HybridAuthIdentity.php): failed to open stream: No such file or directory

i removed this line in the public function actionLogin() and public function actionSocialLogin() and it worked fine

Yii::import('ext.components.HybridAuthIdentity');

hope this helped someone

#15406 report it
GSTAR at 2013/11/07 05:11am
Popup dialog?

How cam I make the Facebook / Twitter login request appear in a popup rather than on a new page?

#15136 report it
Duarte at 2013/10/10 10:03am
Authentication failed!

I get a exception "Authentication failed! Facebook returned an invalid user id."

I tried set CURLOPT_CONNECTTIMEOUT to 60, and set false CURLOPT_SSL_VERIFYPEER in base_facebook.php, but continue not work.

You can help me?

Thank you.

#13584 report it
samilo at 2013/06/08 09:36am
good job

Thank you good job

#13269 report it
zainiafzan at 2013/05/19 04:30pm
Awesome

Your article gave me an inspiration....

#12840 report it
shiv at 2013/04/15 11:09am
i liked it !

good article.

Leave a comment

Please to leave your comment.

Write new article