Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Yii2 remote logout a user session from the user current session

I wanted to logout a user session logged in a different browser/environment from the current session of the same user. A feature similar to this - https://www.facebook.com/settings?tab=security&section=sessions&view.

Yii2 is the backend framework used. Using redis for session management - yii2-redis. I also save the session ids saved in database.

I followed this article - http://www.codeinphp.com/general/php-code-snippets/remotely-destroy-different-session-php-forced-user-signout/

But didn't had any success.

session_id($old_session_id);
session_start(); // This line throws error.
session_destroy();

Deleting the key in redis using \Yii::$app->session->destroySession($oldSessionId) didn't logout.

Changing the session id to old one and then destroying the session also didn't work.

$currentSessionId = \Yii::$app->session->getId();
\Yii::$app->session->setId($oldSessionId);
\Yii::$app->getSession()->destroy();
\Yii::$app->session->setId($currentSessionId);

If anyone had success in implementing this successfully, please share your solution. Also if there is any documentation regarding this which can help, please do provide.

like image 344
Gowrav Avatar asked Aug 11 '15 17:08

Gowrav


2 Answers

The first, session_start() must be call before session_id() and just call only once

if (session_status() == PHP_SESSION_NONE) {
   session_start();
}
session_id($old_session_id);
session_destroy();

But just remove session, that is not enough if you allow user auto login because browser will auto login by using cookies. To solve, you must change user AuthKey - Yii2 use AuthKey to validate user auto login. By default each user have only one AuthKey in user table so that when you change AuthKey user logout anywhere. So we have to custom. Create for each user session an AuthKey, stored somewhere not in user table. Do it easy: extends yii\web\User class override afterLogin function to create AuthKey for each login session. override validateAuthKey function to validate auto login use our custom AuthKey. Now when you want to kill any user session : kill PHP session id and AuthKey that session will be logout right away. I have been using this solution for my projects and it works fine.

like image 136
Ngô Văn Thao Avatar answered Nov 14 '22 22:11

Ngô Văn Thao


Based on Ngo's answer, I figured out a method that works well and is easier to setup.

1) Add a "last_session_id" field to your user table.

2) Add following to your main controller:

public function afterAction($action, $result)
{
    $result = parent::afterAction($action, $result);

    if(Yii::$app->user->id)
    {
        //update the user table with last_session_id
        $user = User::find()->where(['id' => Yii::$app->user->id])->one();
        $user->last_session_id = Yii::$app->session->id;
        $user->save(false);
    }

    return $result;
}

3) Change site/login action to following:

public function actionLogin()
{
    if (!\Yii::$app->user->isGuest) {
        return $this->goHome();
    }

    $model = new LoginForm();
    if ($model->load(Yii::$app->request->post()) && $model->login()) {

        //delete previous session ID and change auth key
        Yii::$app->session->destroySession(Yii::$app->user->identity->last_session_id);
        $u = \common\models\User::find()->where(['id' => Yii::$app->user->id])->one();
        $u->auth_key = Yii::$app->security->generateRandomString();
        $u->save(false);
        return $this->goBack();
    } else {
        return $this->render('/site/login', [
            'model' => $model,
        ]);
    }
}
like image 39
Nate Avatar answered Nov 15 '22 00:11

Nate