Hey, if people log into my app from more than one tab/browser they’re going to have problems.
So, when a user logs in, I’d like to log them out everywhere else, and park them on a “you logged in somewhere else” page.
I tried a couple things: Accounts.logoutOtherClients() looked promising, but seems to be broken. This logs everyone out.
if (Meteor.isClient) {
// FF 1 tab, Chrome 2 tabs.
// FF login -> chrome logs out ok.
// Chrome login -> FF logs out. Then Chrome other tab logs in. Then both Chrome tabs logout.
Accounts.onLogin(function() {
console.log(Meteor.loggingIn()); // false. See https://github.com/meteor/meteor/issues/1616
Accounts.logoutOtherClients();
});
}
Before that I was working on a hand-rolled solution, but it seemed like Meteor.logout() would logout both tabs in the same browser. The best I could get was window.location="https://google.com"
NOTE: The approach below doesn’t work if user closes all tabs. When they re-open app, they can never login again.
What’s the way to do this?
The best way I can think to do this is:
- At Meteor.start() on the client make a unique tabToken
- Save token to Session variable on client
- At login save tabToken to user
- On client, listen to Meteor.user().profile for tabToken changes.
if (Meteor.isClient) {
// Make a unique tabToken at startup.
Meteor.startup(function() {
var tabToken = (0|Math.random()*9e6).toString(36); // jshint ignore:line
Session.set('tabToken', tabToken);
console.log('startup TabToken ' + Session.get('tabToken'));
});
// onLogin, set the active tab to our tabToken
Accounts.onLogin(function() {
Meteor.call('setActiveTab', Session.get('tabToken'), function() {
// When method returns, watch profile for tabToken changes
console.log('setActiveTab tabToken ' + Session.get('tabToken'));
console.log('setActiveTab Meteor.user().profile.tabToken ' + Meteor.user().profile.tabToken);
Tracker.autorun(function (c) {
// If the tabToken changes to a different token, logout
if (Meteor.user()) {
var userTabToken = Meteor.user().profile.tabToken;
if (userTabToken && !Session.equals('tabToken', userTabToken)) {
window.location = 'https://google.com';
// Doesn't work
// c.stop();
// Meteor.logout(); // ERROR this logs out all tabs in browser.
// Router.go('loggedOut');
}
}
});
});
});
}
// Make a meteor method to set tabToken
if (Meteor.isServer) {
Meteor.methods({
setActiveTab: function(tabToken) {
if(!tabToken) throw new Meteor.Error('noTabToken');
console.log('setActiveTab ' + tabToken);
if (!Meteor.user()) return;
Meteor.users.update(Meteor.userId(), {
$set: {
'profile.tabToken': tabToken
}
});
}
});
}
This just seems really kludgy. Any other suggestions?
Mike