0

When logging in on my site you have the option to "remember me". This will set a "remember me" cookie called "R" with a userid and a token. When the session cookie expires, which is set to 1 day (86400 seconds), the "remember me" cookie should start a new session.

When I test it, I'm setting the session cookie lifetime to 60 seconds. After the expiration date passes the "remember me" cookie starts a new session. But after an hour or so, it won't start a new session anymore and a user has to login again even though the "remember me" cookie still exists.

The token is saved in the database. There is no bug where the hashed cookie is being validated. The user is found.

I've used the following guide on Stackoverflow: Keep me logged in

My code:

// Session class

private $_logged_in = false;
public  $user_id;
public  $userlevel;

function __construct() {
    session_name('connected');
    session_set_cookie_params(24*60*60);
    ini_set('session.gc_maxlifetime',86400);
    session_start();
}

public function is_logged_in() {
    if(isset($_COOKIE['R'])) {
        $this->check_cookie();
        return $this->_logged_in;
    } else {
        $this->check_login();
        return $this->_logged_in;
    }
}

private function check_login() {
    if(isset($_SESSION['user_id'])) {
        $this->user_id = $_SESSION['user_id'];
        $this->userlevel = $_SESSION['userlevel'];
        $this->_logged_in = true;
    } else {
        unset($this->user_id);
        unset($this->userlevel);
        $this->_logged_in = false;
    }
}

public function check_cookie() {
        $cookie = $_COOKIE['R'];
        list($user, $token, $mac) = explode(':', $cookie);
        if($mac !== hash_hmac('sha256', $user . ':' . $token, SECRET_KEY)) {
            $this->_logged_in = false;
        }
        if($user = User::find_by_id($user)) {
            if($user->rememberme == $token) {
            new Session();
            $this->user_id = $_SESSION['user_id'] = $user->id;
            $this->userlevel = $_SESSION['userlevel'] = $user->userlevel_id;
            $this->_logged_in = true;  
            }
        }
}

public function login($user, $rememberme = "") {
    if($user && $rememberme == "") {
        $this->user_id = $_SESSION['user_id'] = $user->id;
        $this->userlevel = $_SESSION['userlevel'] = $user->userlevel_id;
        $this->_logged_in = true;
    } elseif($user && $rememberme == 'rememberme') {
        $this->user_id = $_SESSION['user_id'] = $user->id;
        $this->userlevel = $_SESSION['userlevel'] = $user->userlevel_id;
        if($user->setRememberMe($this->user_id)) {
        $this->_logged_in = true;
        } 
    }
}
Community
  • 1
  • 1
Nijn
  • 392
  • 4
  • 22
  • I did.. It runs everything as it should. A new session cookie is made after it expires and the remember me cookie is checked. However after 30 minutes or so, without changing the code or anything, I'm logged out. – Nijn May 09 '14 at 10:46
  • That’s not what I’d call debugging … after those 30 minutes, when it does “not work”, see what values you get in your `check_cookie`, whether the hashes match, finding the user via id works, etc. – _that_’s debugging. – CBroe May 09 '14 at 10:52
  • Turns out that I made an obvious mistake with the system. The rememberme token is saved once. If a user changes browser or device a new token is made and saved in the database. When a user goes back to the site with his previous browser/device, the token in that cookie no longer matches the one in the database. How do you deal with this problem.. – Nijn May 12 '14 at 11:49
  • Either don’t create a new token and use the same one for different devices, or safe multiple tokens … Before doing that, you should carefully consider what security implications each approach might have, and if you should take any additional measures (like tie a token to a device “fingerprint”, use an expiry time so that [unused] tokens can not be used to log in again for all eternity, etc.) – CBroe May 12 '14 at 17:18

0 Answers0