Yii Framework Forum: Implementing Facebook Login - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Implementing Facebook Login Review my code and help me improve it Rate Topic: -----

#1 User is offline   Anonymous Joe 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 13
  • Joined: 31-August 12

  Posted 17 November 2012 - 04:22 AM

Hi guys,

I'm trying to implement a Facebook login on my test application. There are extensions out there but I just don't feel comfortable using it. I'm just thinking to implement a simple and basic authentication that does only what you require. I've dug around in Yii forum to see how others have implemented it and also learned more on Yii's basic authentication tutorial especially on the authentication flow.

Here's my code so far.

login.php
<p>
	<?php echo CHtml::link("Login with Facebook", array('site/facebook')); ?>
</p>


SiteController.php
<?php
public function actionFacebook()
{
	$model=new LoginForm;
	if($model->facebook())
		$this->redirect(Yii::app()->user->returnUrl);
}
?>


models/LoginForm.php
<?php
public function facebook()
{
	Yii::import('application.vendors.facebook.Facebook');
	$facebook = new Facebook(array(
		'appId'  => Yii::app()->params['facebookApi'],
		'secret' => Yii::app()->params['facebookSecretCode'],
		'cookie' => true,
	));
	$loginUrl = $facebook->getLoginUrl(array());
	$facebookUid = $facebook->getUser();
	if(!empty($facebookUid))
	{
		$facebookProfile = $facebook->api('/me');
		if(!empty($facebookProfile))
		{
			$user = User::model()->findByAttributes(array('oauth_provider' => 'facebook', 'oauth_uid' => $facebookProfile['id']));
			if($user === null)
			{
				$user = new User;
				$user->oauth_provider = 'facebook';
				$user->oauth_uid = $facebookProfile['id'];
				$user->group_id = 2;
				$user->username = $facebookProfile['username'];
				$user->name = $facebookProfile['name'];
				$user->status = 1;
				$user->ip = $_SERVER['REMOTE_ADDR'];
				$user->created = time();
				$user->modified = time();
				$user->save(false);
			}
			$identity = new UserIdentity($user->id, $user->oauth_uid, $user->oauth_provider);
			$identity->authenticate(true);
			switch($identity->errorCode)
			{
				case UserIdentity::ERROR_NONE:
					$duration = 3600*24*30; // 30 days
					Yii::app()->user->login($identity, $duration);
					return true;
					break;
				case UserIdentity::ERROR_STATUS_NOTACTIV:
					exit('account not active'); //Not very sophisticated
					return false;
					break;
				case UserIdentity::ERROR_STATUS_BAN:
					exit('account banned'); //Not very sophisticated
					return false;
					break;
			}
		}
	}
	else
	{
		echo "<script type='text/javascript'>top.location.href = '$loginUrl';</script>"; //Redirect user to Facebook login page
		exit;
	}
}
?>


components/UserIdentity.php
<?php
class UserIdentity extends CUserIdentity
{
	private $_id;
	public $oauth_uid;
	public $oauth_provider;

	const ERROR_STATUS_NOTACTIV=4;
	const ERROR_STATUS_BAN=5;

	public function authenticate($facebook = false)
	{
		if($facebook)
		{
			Yii::import('application.vendors.facebook.Facebook');
			$facebook = new Facebook(array(
				'appId'  => Yii::app()->params['facebookApi'],
				'secret' => Yii::app()->params['facebookSecretCode'],
				'cookie' => true,
			));
			$facebookUid = $facebook->getUser();
			$user = User::model()->findByAttributes(array('oauth_provider' => 'facebook', 'oauth_uid' => $facebookUid));

			if($user === null)
			{
				$this->errorCode=self::ERROR_USERNAME_INVALID;
			}
			else if($user->status==0)
				$this->errorCode=self::ERROR_STATUS_NOTACTIV;
			else if($user->status==-1)
				$this->errorCode=self::ERROR_STATUS_BAN;
			else
			{
				$this->_id = $user->id;
				$this->oauth_uid = $user->oauth_uid;
				$this->oauth_provider = $user->oauth_provider;
				$this->username = $user->username;
				$this->errorCode=self::ERROR_NONE;
			}
		}
		else {
			$record = User::model()->findByAttributes(array('username' => $this->username));
			if($record === null)
				$this->errorCode=self::ERROR_USERNAME_INVALID;
			else if(!$record->validatePassword($this->password))
				$this->errorCode=self::ERROR_PASSWORD_INVALID;
			else
			{
				$this->_id = $record->id;
				$this->username = $record->username;
				$this->errorCode=self::ERROR_NONE;
			}
		}
		return $this->errorCode==self::ERROR_NONE;
	}

	public function getId()
	{
		return $this->_id;
	}

}
?>

I think I could improve on the error handling especially models/LoginForm.php. Unlike form based login where we can use
$this->addError('attribute','error message')
, Facebook login is form-less on the application itself. So I need some other way to show the error, perhaps a flash message. What do you guys think?

Also, should saving of new users be done in models/LoginForm.php or components/UserIdentity.php? What do you guys think?

I'm still learning Yii as a matter of fact so please review it and let me know how I can improve it.
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users