How to programmatically log out lots of users


(eriko) #1

So I need to end a bunch of people login sessions at once on a quarterly basis. I notice that admin/users.rb log_out uses MessageBus.publish "/logout", @user.id, user_ids: [@user.id]. Can I use that inside a plugin to mass logout users? I have ‘log out strict’ set so it should hit all the sessions.


Reset all login tokens
(Sam Saffron) #2

That just informs them they are logged out

To log out you have to invalidate the cookie, by cycling it in the user table


(Jeff Atwood) #3

Would replacing all the cookie database columns (for users) with null also work?


(Sam Saffron) #4

Yeah, but the users would think they are logged in unless the message is sent


(eriko) #5

So both the message to let the user know and nulling out the cookie columns . Thanks

That said I am not finding any cookie columns. What are they attached to?

It is the @user.auth_token = nil that would do this?


(Sam Saffron) #6

Yeah it’s the auth token column


(Felix Freiberger) #7

Isn’t there an easy way to trigger the force-logout functionality for all users from the rails console?
(I’m also interested in this.)


(eriko) #8

It would be interesting if there was. That said I am trying to set this up in low complexity manner that requires little human intervention. In this case I have added this to a plugin that I use to import/manage users. We have a closed garden with a constrained poll of people (a college) so we have to maintain the enrollment a little more closely.


(Sam Saffron) #9

You could iterate through all user records, nil the auth token and ship the message to them telling them they are logged off.


(Mittineague) #10

Sorry if I’m missing the obvious, but wouldn’t putting the forum into “read only mode” be effectively the same as logging everyone off?


(Régis Hanol) #11

Nope. Read only mode will prevent login (for anon) and posting (for logged in users) but once disabled it will not force users to log back in.


(eriko) #12

This is what I have done. Thanks for the confirmation. It works very well.

The following is a chunk of code from inside a job created by a plugin. The SiteSetting.iu_logout_enabled is defaulted to false.

if SiteSetting.iu_logout_enabled
  User.where.not(auth_token: nil, admin: true, moderator: true).find_each do |user|
    user.update_attribute auth_token: nil
    MessageBus.publish "/logout", user.id, user_ids: [user.id]
  end
end

(Régis Hanol) #13

Where is SiteSetting.iu_logout_enabled coming from?


(eriko) #14

Sorry that is a ui setting from the plugin that contains this. This is wrapped inside a job but is turned off by default. (edited my previous reply)


(Felix Freiberger) #15

As an alternative, here is a bit of JavaScript for node.js that iterates over a list of user ids and logs them out using the API:

var logoutUsers = function (ids, domain, apiKey, delay) {
    var nextIndex = 0;
    var errors = 0;

    var callNextUrl = function () {
        if (nextIndex < ids.length) {
            var id = ids[nextIndex];
            nextIndex++;
            console.log("logging out " + id);
            var req = https.request({
                hostname: domain,
                port: 443,
                path: '/admin/users/' + id + '/log_out?api_key=' + apiKey + '&api_username=system',
                method: 'POST'
            }, function (res) {
                console.log("response: " + res.statusCode);
                res.resume();
                setTimeout(callNextUrl, delay);
            }).on('error', function (e) {
                console.log("Got error: " + e.message);
                errors++;
            });
            req.end();
        } else {
            console.log("Done!");
            console.log("Errors: " + errors);
        }
    };

    callNextUrl();
};

How do I get a list of all users from the API?
Re-purposing a Discourse installation for a yearly event