Auto login after registration (fake login)

Hi there,

I just wondered which practice is the best for making an automatic login, after a user has registered himself.

Or if i, as admin, would like to login as another user, how do i then "fake" the login?

Thanks :)

I do it like this, after user has registered:


// $user == new created user record with Login and Password assigned from form

$identity=new UserIdentity($user->Login,$user->Password);

$identity->authenticate();

Yii::app()->user->login($identity,0);



Okay, thanks, but you could imagine in some rare case, something extraordinary or if the password is encrypted, the authentication would fail… I’m looking fore some 100% way of logging in a user.

Yeah, i thought about these issues, too.

About encryption: i usually add a public $Password to my user class and use CryptPassword as column name. CryptPassword is not visible in forms. I only overwrite it with encrypted password, if Password is set. So no problem with that.

Regarding these rare error condidtions: They should really only happen, if e.g. user record is updated in the same moment when login happens. To catch that you could add a line like:


if (Yii::app()->user->IsGuest)

  throw new CException('Something really dumb has happened: you could not get logged in after registration. Please use the login form to login.');

I do something similar, but it’s still not a perfect solution, and i can’t use it to create an admin “simulate login” functionality.

From checking the sources of CUserIdentity/CBaseUserIdentity, something like this should also work:


$identity=new UserIdentity($someUsername,'');

$identity->error=UserIdentiy::ERROR_NONE;


// to logout admin, if logged in:

if (!user()->isGuest)

  user()->logout();


user()->login($identity,0);

Thats precisely what i do know, but again, it’s not perfect, and could be broken by some later update.

It should be update safe as it’s pretty much the same what you do in authenticate() anyway. You could put that code into a forceLogin() method to your UserIdentity. So if things change one day, you only have to touch one class.

Mike is right. Thank you man for a good hint. Here is my working code:


$user=User::model()->findByPk($userID);

if($user===null) {

	throw new CHttpException(500, 'Bye');

} else {

	//...

	// Auto-login

	$identity=new UserIdentity($user->email,'');

	$identity->setID($user->id); /* had to add WebUser::setID() since WebUser::$_id is private */

	$identity->errorCode=UserIdentity::ERROR_NONE;

	Yii::app()->user->login($identity,0);

	//...

}

In my case auto-login failed right untill I added


$identity->setID($user->id);

Hope it’ll help somebody. Love Yii!

1 Like

I’ve thought about a even cleaner solution. Actually i think it’s the responsibility of UserIdentity to create a authenticated user. So a better implementation might be:


//UserIdentity:

public static function createAuthenticatedIdentity($id) {

    $identity=new self;

    $identity->setID($id);

    $identity->errorCode=self::ERROR_NONE;

    return $identity;

}


// Usage:

Yii::app()->user->login(UserIdentity::createAuthenticatedIdentity($userId),0);

The solution of Mike is really good and clean.

Another option is to add a boolena parameter to authenticate checkPassword.

But maybe the method of Mike is more elegant.

it will produces an error

Missing argument 1 for CUserIdentity::__construct(), called in C:\wamp\www\tcc\protected\modules\customer\components\UserIdentity.php on line 48 and defined

Change the method to:





    public static function createAuthenticatedIdentity($username)

    {

        $identity=new self($username,'');

        $identity->errorCode=self::ERROR_NONE;

        return $identity;

    }



EDIT: Changed $id to $username. If you have more attributes in your UserIdentiy class that you want to set, you could add more arguments to this method and set them here, too.

i try to implemented your solution mike.

but it gives me an error


Property "UserIdentity.id" is read only

Ok, tried to make the example above more generic. Can you try again?

because the problem an id is read only, then i changed variable id to _id like this:




$identity->_id=$id;



the complete code is like this:




public static function createAuthenticatedIdentity($id) {

    	$identity=new self($id,'');

    	$identity->_id=$id;

    	$identity->errorCode=self::ERROR_NONE;

    	return $identity;

}



now it works.

thanks for your clue mike…

you’re great…

Take a look at the fixed example above. You should not have to set _id manually anymore.

In the link below I found a different approach. It is definetly cleaner:

http://www.redbookmedia.com/2010/05/auto-login-with-yii/

Here I paste the code:




// UserIdentity is your extended class of CUserIdentity

$identity=new UserIdentity($userId, $pwd);

$identity->authenticate();

if ($identity->errorCode == UserIdentity::ERROR_NONE)

{

	$duration= 3600*24*30; // 30 days

	Yii::app()->user->login($identity,$duration);

	$this->redirect("your destination");

}

else

{

	// went south, // error processing

}



chirvo, I don’t see how that solves the problem? You’ve justed pasted the code for a standard login procedure?

Here is what I am using





	$identity = new UserIdentity($username, $password);

	$identity->authenticate();

	Yii::app()->user->login($identity, $duration = 0); // Do not remember Auto login user