Difference between #4 and #5 of Integrating HybridAuth directly into Yii without an extension

unchanged
Title
Integrating HybridAuth directly into Yii without an extension
unchanged
Category
How-tos
unchanged
Tags
Authentication, HybridAuth
changed
Content
This article tries to explain the steps required in integrating the
[HybridAuth](http://hybridauth.sourceforge.net/) into Yii directly, without
using an extension. 

The reason for not using an existing extension, such as
[hoauth](http://www.yiiframework.com/extension/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:
~~~
[html]
<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:
~~~
[html]
<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:
~~~
[php]
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',);'linkedin',);
    
    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","id", 
                        "secret" => "google
secret","key",
                    ),
                    "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","id", 
                       "secret" => "facebook
secret","key",
                   ),
                   "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","key", 
                       "secret" => "linkedin
secret","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:

~~~
[php]
"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():
~~~
[php]
    //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():
~~~
[php]
    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:
~~~
[php]
    //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.
~~~
[php]
    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.
Write new article