Meteor Accounts - remember me option

Hi

I know you can set amount of days the login token is valid for, something like:
Accounts.config({
loginExpirationInDays: 14
})

However I want to have a checkbox on the login form for ‘Remember me’. Basically if the user doesn’t check it, login would expire once you close the browser (session based). If user checks the checkbox it would create a token for him for let’s say 14 days. How can I do it? It seems I can’t change this value once I set it?

2 Likes

‘Remember me’ is the default behaviour in the Accounts package, but you can use LocalStorage for this:

  • If not checked:
function () {
  Accounts.loginWithPassword();
  // stops Accounts from logging you out due to token change
  Accounts._autoLoginEnabled = false;
  // remove login token from LocalStorage
  Accounts._unstoreLoginToken();
  // if you want to synchronise login states between tabs
  var pollLoginState = function () {
    var currentLoginToken = Accounts._storedLoginToken();
    if (! currentLoginToken) return;

    // != instead of !== just to make sure undefined and null are treated the same
    if (Accounts._lastLoginTokenWhenPolled != currentLoginToken) {
      if (currentLoginToken) {
        Accounts.loginWithToken(currentLoginToken, function (err) {
          if (err) {
            Accounts.makeClientLoggedOut();
          }
        });
      } else {
        Accounts.logout();
      }
    }

    Accounts._lastLoginTokenWhenPolled = currentLoginToken;
  };

  setInterval(function () {
    pollLoginState();
  }, 3000);
}
  • If checked, login as normal
5 Likes

Thanks a lot, works fine!

1 Like

Where exactly I’m supposed to put this piece of code? Thanks and sorry for the stupid question.

Use it in the function where you call Accounts.loginWithPassword() on the client

So for e.g. with Blaze:

Template.loginPage.events({
  '#login-button': function () { 
    if (rememberMeCheckboxIsChecked) {
      // login as usual
    } else {
      // manage localstorage manually (with above code)
    }
  }
});

Tried this but it’s not working for me. If the remember me is unchecked, user stays logged in even if window is closed and reopened.
What am I doing wrong? Is the Accounts.loginWithPassword different than Meteor.loginWithPassword?
I can see the polling is working but I don’t understand how it is supposed to work when user closes the browser and opens a new one.

Thanks for the help

Template.loginPage.events({
  '#login-button': function (event) { 
    var email = event.target.email.value;
    var password = event.target.password.value;

    if (rememberMeCheckboxIsChecked) {
        Meteor.loginWithPassword(email, password)
    } else {
        Meteor.loginWithPassword(email, password)
        Accounts._autoLoginEnabled = false;
              // remove login token from LocalStorage
        Accounts._unstoreLoginToken();
              // if you want to synchronise login states between tabs
        var pollLoginState = function () {
            var currentLoginToken = Accounts._storedLoginToken();
            if (! currentLoginToken) return;

            // != instead of !== just to make sure undefined and null are treated the same
            if (Accounts._lastLoginTokenWhenPolled != currentLoginToken) {
                if (currentLoginToken) {
                    Accounts.loginWithToken(currentLoginToken, function (err) {
                    if (err) {
                       Meteor.logout();
                    }
                    });
                } else {
                    Meteor.logout();
                }
            }

            Accounts._lastLoginTokenWhenPolled = currentLoginToken;
        };
        setInterval(function () {
            pollLoginState();
        }, 3000);
    }
  }
});

This probably means the login token isn’t being removed from LocalStorage for whatever reason, so you may want to try doing it manually:

localStorage.removeItem('Meteor.loginToken');
localStorage.removeItem('Meteor.loginTokenExpires');
localStorage.removeItem('Meteor.userId');

// to ensure that the localstorage poller doesn't end up trying to
// connect a second time
Accounts._lastLoginTokenWhenPolled = null;

The localstorage key names are found here

The polling is only for keeping the same user between tabs while they have the website open (or logging them out on all tabs)

& yeah, it should be Meteor.loginWithPassword

still doesn’t work. In the console, localStorage before and after the removeItem statement stays the same (token is kept). Only if I use localStorage[“Meteor.loginToken”]=null in the console and then close the browser, it indeed logs out.
Any ideas?

It’s working for me, it might be your browser - your method is valid too though

Meteorbeginner is right, the solution doesn’t work as is because it must be a callback in loginWithPassword, see below…

        //store in a var before logging in
        var bRememberMe = $('#htmlIdLoginRememberMe:checked').length > 0;

        Meteor.loginWithPassword(
            $('[name=htmlNameLoginEmail]').val(),
            $('[name=htmlNameLoginPassword]').val(),
            function(error){
                if(error){
                    //handle error here, no login occured
                }
                else {
                    //login occured
                    if (bRememberMe == false) {
                        //remove login token after login occured, else it doesn't work
                        Accounts._unstoreLoginToken();
                        Accounts._autoLoginEnabled = false;
                    }
                }
            }
        );
1 Like

This is the correct answer.
Thanks!

Well, now every time I hit refresh, if the user didn’t check the ‘remember me’, it immediately logs out…
this is so frustrating, I don’t understand why simple and most straightforward features become a nightmare in Meteor.

1 Like

This is the correct behaviour, no? LoginToken removed = log out on session end = (page refresh || closed browser)

That’s the behavior you want. You refresh, you log out.

1 Like

For anyone still interested in this functionality who will find the topic.

Recently I published a dependency for this:

Basically the only thing you have to change is to use a wrapper for Meteor.loginWithPassword. From now you will be able to give the rememberMe option as a last parameter to the method.

I can see issues in the previous ideas which are not there in my implementation:

  • this dependency won’t trigger any unneeded onLogin callbacks on the client/server after resume,
  • reconnecting to server won’t log out the user despite having rememberMe set as “false”
1 Like

Have you thought about attaching it to Meteor? For example, Meteor.loginWithPasswordAndForget(user, password, [callback])

It would not be a problem to do it but personally I prefer to not do that.
I know that it can be way easier to use for people when it would be directly in the global of Meteor.
However I like the separation between modules. I feel like as long as it’s not an official Meteor thing it should not be attached to the Meteor to not confuse aynone or override something in the future by accident.

So currently if someone would want to do that then he would have to do it manually by himself like:

Meteor.loginWithPasswordAndForget = (user, password, callback = () => {}) => {
   RememberMe.loginWithPassword(user, password, callback, false);
}

No! Is not the way that web works.
Sessions only ended when you close the browser, not when you refresh the page!

It surprises me that until now no one has resolved this decently.
Meteor is totally abandoned, unfortunately.
No decent improvement, no innovation…
Wake up MDG!!!

1 Like

Hello,

Have you checked Meteor-Remember-Me Package?

Thanks for the package tprzytula! Works great! Solved my problem.