User Authentication Best Way

I have been playing around with the "UserIdentity" class and I am having difficulty understanding what each thing is for.

I want to have authentication and role based permission system in my application so "UserIdentity" is the best way for going about this?

"UserIdentity" is accessed in the application using "Yii::app()->user", correct?

However at the same time I have realized that storing all user database "record" information in "UserIdentity" is not really the best way as the password will also be stored in the "session" along with all other information.

In other words I am having difficultly wrapping my head around the "User Authentication" versus the "User Model" and "database access" can someone shed some light on this?

My original plan was just to put the entire user database record in the session, but this is apparently not a good thing correct?

You see, I really want the "User Session", "User Identity", and "User Model" to be joined together somehow, but without storing the sensitive information such as the password in the session. I also want to be able to call "User Model" methods on the session rather than just "setting states" with the variables. Any ideas?

What do YOU store in the session, just the user ID?

Also, what is the importance of using "UserIdentity", I mean why have your authentication method in there, and not in the controller action?

Is it because when it comes to using Yiis user permission system, and other methods, Yii looks for the authentication method there?

Don’t become confused here.

Yii::app()->user->setState is not the same as Yii::app()->user.

About UserIdentity, let me quote the code:


/**

 * UserIdentity represents the data needed to identity a user.

 * It contains the authentication method that checks if the provided

 * data can identity the user.

 */



That’s it.

It talks to the User::model(). Where the data is - password, username, email, etc.

Usually there is a UserController too.

So don’t get it all mixed up.

setState is inherited from CBaseUserIdentity from which CUserIdentity is derived.

Take a peek at it all.

That’s one - if not the best - way of getting to know Yii.

If you want a full example of how it all fits together, I’d recommend that you study Yii-User:

http://www.yiiframework.com/extension/yii-user

Highly recommended, by the way.

Is it best to seperate the "User Model" from the "Yii::app()->user" and "User Identity".

How do you mean separate them?

They’re definitely distinct, but they’re still going to be linked.

The User Identity just gives you a means of consolidating authentication code and persistently storing some of the most basic information about the current user for quick access (like their user model ID for permission checking, etc), but it’s going to be completely independent of the actual model you use to store your user’s detailed information.

Thanks thats similar to what I was trying to get at. You have cleared up my confusion and given me the reassurance I need.

They are separate.

View UserIdentity as a special controller which function is to identify the user.

Do yourself a favor and take a look at yii/framework/web/auth/CUserIdentity and yii/framework/web/auth/CBaseUserIdentity.php.

Then take a look at UserIdentity from Yii::user:




<?php


/**

 * UserIdentity represents the data needed to identity a user.

 * It contains the authentication method that checks if the provided

 * data can identity the user.

 */

class UserIdentity extends CUserIdentity

{

	private $_id;

	const ERROR_EMAIL_INVALID=3;

	const ERROR_STATUS_NOTACTIV=4;

	const ERROR_STATUS_BAN=5;

	/**

     * Authenticates a user.

     * The example implementation makes sure if the username and password

     * are both 'demo'.

     * In practical applications, this should be changed to authenticate

     * against some persistent user identity storage (e.g. database).

     * @return boolean whether authentication succeeds.

     */

	public function authenticate()

	{

		if (strpos($this->username,"@")) {

			$user=User::model()->notsafe()->findByAttributes(array('email'=>$this->username));

		} else {

			$user=User::model()->notsafe()->findByAttributes(array('username'=>$this->username));

		}

		if($user===null)

			if (strpos($this->username,"@")) {

				$this->errorCode=self::ERROR_EMAIL_INVALID;

			} else {

				$this->errorCode=self::ERROR_USERNAME_INVALID;

			}

		else if(Yii::app()->controller->module->encrypting($this->password)!==$user->password)

			$this->errorCode=self::ERROR_PASSWORD_INVALID;

		else if($user->status==0&&Yii::app()->controller->module->loginNotActiv==false)

			$this->errorCode=self::ERROR_STATUS_NOTACTIV;

		else if($user->status==-1)

			$this->errorCode=self::ERROR_STATUS_BAN;

		else {

			$this->_id=$user->id;

			$this->username=$user->username;

			$this->errorCode=self::ERROR_NONE;

		}

		return !$this->errorCode;

	}

	

	/**

	* @return integer the ID of the user record

	*/

	public function getId()

	{

		return $this->_id;

	}

}

As you can see, it asks User (the model) about username, email and password.

It makes it possible to refer to the current active user as Yii::app()->user Yii::app()->user->name and Yii::app()->user->id.

That CBaseUserIdentity carries convenience functions for setting/getting persistent state does not mean that the User model is stored in it.

Only id and name (out of the box anyway). ;)

Model, Controller and UserIdentity work together.

And nothing is stored in the user session, unless you do so by calling Yii::app()->user->setState(‘whatever’, $what_ever).

I know what you mean about the user model, being used in the user identity. At the end of the day its more than likely up to personal preference on the application is designed. But I like the analogy of having the User Identity / Session seperated from the Model because that was closer to my original thoughts about how it would work.

Thanks for the advice anyways.

Yes, but it isseparate.

The UserIdentity class that I quoted in its entirety, is only using the user model.

It has nothing to do with it, but is uses it to get the current user.

If you don’t want to use UserIdentity, fine.

But then you have to figure out how to get the current user.

And the only thing it grabs from User is the id.

Nothing else.

It doesn’t touch the session, it doesn’t touch the User model.

Your user model and user controller are tied to each other, of course.

The UserIdentity could have used a retina scan to identify the current user.

It’s up to you. :)