Close all sessions for one user using code

Hello, could someone give me a clue on how to close all sessions for a specific user using code, why do I want to do this? because I need to be sure that only one session per user is active, for security reasons. I discovered how to get all the users that use code, but not for a specific one, I really appreciate your help.

1 Like

I don’t think that’s currently possible out of the box; while sessions are typically (but not always!) stored in the modx_session table, there’s no easy way to get all sessions only for a specific user. You’d need to loop over all sessions (which can easily get into the hundreds of thousands of records on a decently sized site), and inspect the serialised data to find any sessions belonging to the user.

What you could try doing is adding a plugin that fires when a user logs in. In that event, log the user ID ($user->get('id')), the session ID (session_id()), and any additional information you want (maybe the users’ IP address or browser) into a custom database table. Then, you can use that custom table to list users’ sessions.

To prevent users being logged in multiple times, you could use your custom table to check for existing sessions in the OnBeforeWebLogin event. Either deny the login ($modx->event->output(false)), or get the session from the stored ID ($modx->getObject('modSession', ['id' => $storedSessionId])) and remove it to logout the other session.

Obviously this approach is not going to work with non-database sessions.

2 Likes

not easy to solve, because there are situations, where the same session-item is reused for different users. See

3 Likes

Well, that sounds complicated, I’m going to think a little bit about what other way I could offer a similar functionality to the client. Thanks @markh and @bruno17

1 Like

If you logged the logins, user id#, sessions and ips upon login you would at least have some data you could use for policing the users. You could look for users that logged in frequently or check the log for users with multiple IPs

I think one of the huge problems is, the end of a session may be undetermined, for example I go to the site, then close my browser, then go to another device, the session is still going to be there.

A snippet that does part of the work could act like login, take the user name and pass, then that’s got to be authenticated.

It might even be able to be a posthook on login, which collects the user id, ip, etc., and then logs that data along with session id

Thank you @nuan88, just one more question just to make me sure, all this api funcions -> https://docs.modx.org/current/en/extending-modx/core-model/moduser
Works only for the current active session?

Yes, most of those are related to the current session and only work as expected when the user is the currently logged in user. Only some modUser methods (like isMember) will work on any user object.

1 Like

Thank you @markh , finally I did what you recommend me, it wasn’t so hard and it seems to work.
I created a table that stores id, session id and username. Still no problem with reused session-item that @bruno17 said.

<?php

$package_path = $modx->getOption('core_path').'components/modcontrolsession/model/';
$modx->addPackage('modcontrolsession', $package_path);

    switch ($modx->event->name) {
    case 'OnWebLogin':
        $iduser = $user->get('id');
        $username = $user->get('username');
        $idsession = session_id();
        $saveResource = $modx->newObject('ControlSessions',array(
           'id_user' => $iduser,
           'session' => $idsession, 
           'user_name' => $username, 
        ));
         $saveResource->save(); 
    case 'OnBeforeWebLogin':
        $user = $modx->getObject('ControlSessions',array(
            'user_name' => $username));
        if(isset($user)){
            $session = $user->get('session'); 
            $modx->removeCollection('ControlSessions', array('session' => $session));
            $modx->removeCollection('modSession', array('id' => $session));
            $idsession = session_id();
            $saveResource = $modx->newObject('ControlSessions',array(
               'id_user' => $iduser,
               'session' => $idsession, 
               'user_name' => $username, 
            ));
            $saveResource->save(); 
        }   
}
6 Likes