1

I'm trying to make a remember me function for a user login. I think i have the basics covered.

If the auth_tokens table should for some reason be leaked, impersonation is prevented by not having the cookie value equal to the table values (base64_encode/base64_decode). (They can be decoded and used but its at least a bit more work to steal an account)

No user information is stored in the cookie.

When a user successfully logs in with the remember me cookie, a session is set to prevent the database from getting useless requests.

A new selector, token and expire date is crated at each login

So my question now is, are there a way to prevent someone from stealing a cookie value and then creating the remember me cookie to successfully log in as that user?

And is the way I'm using session's secure or is it possible for someone to set these to what ever value they would want?

And my last question. Should the USER_ID in the AUTH_TOKENS table also be encoded to make it harder guessing what user the tokens belong to? If so how would I then select the correct user id from the user table when needed.

if(auto login) {
 $expire = time() + 3600 * 24 * 30; // Cookie expire time
 $expire_encoded = base64_encode($expire); // Expire encoded
 $token_encoded = base64_encode(bin2hex(random_bytes(32))); // 32chars token encoded
 $token = base64_decode($token_encoded); // 32 chars token decoded
 $selector_encoded = base64_encode(bin2hex(random_bytes(16))); // 16 chars token encoded
 $selector = base64_decode($selector_encoded); // 16 chars token decoded
 $userid = 1; // User id
 $value = "$selector|$token"; // Cookie value
 setcookie('remember', $value, $expire, '/', $_SERVER['SERVER_NAME'], true); // Set cookie
 // Insert to db (not an actual function, just for this post. I'm using bind parm)
 insert_db(SELECTOR = $selector_encoded, USER_ID = $userid, TOKEN = $token_encoded, EXPIRES = $expire_encoded, IP = ip, date = date/time)
}
if((isset($_COOKIE['remember']) && (!isset($_SESSION['logged_in']))) {
 $tokens = explode('|',$_COOKIE['remember']);
 $selector = base64_encode($tokens[0]);
 $token = base64_encode($tokens[1]);
 // Select from db (not an actual function, just for this post. I'm using bind parm)
 $row = select_from_db(WHERE SELECTOR = $selector AND TOKEN = $token);
 if(mysqli_num_rows($row) === 1){
 // User logged in
 $_SESSION['logged_in'] = true;
 $_SESSION['user_id'] = $row['USER_ID'];
 // Generate new selector, token and expire date and insert to db
 } else {
 // User not logged in
 }
}

My auth_tokens table looks like this

 +------------------+
 | AUTH_TOKENS |
 +------------------+
 | ID |
 | SELECTOR |
 | USER_ID |
 | TOKEN |
 | EXPIRES |
 | IP |
 | DATE |
 +------------------+
asked Feb 15, 2018 at 12:12
2
  • You could add additional Security by adding the IP to your token in combination with the username. You could also save the IP the user logged in from, so can check if both IP and token are matching. Commented Feb 15, 2018 at 12:20
  • Yeah but, then the user would have to login in on each ip change. I think that kind of defeats the purpose of auto login. Most people have a dynamic ip. Commented Feb 15, 2018 at 12:23

1 Answer 1

1

The remember me token should not be accessible via JavaScript, and should not be transmitted over non secure requests. So if this is the case, how someone can have access to the tokens, if he have access to your database then that's another problem.

So to make a cookie transmitted only over HTTPS requests and hide it from been accessed via JavaScript, you should replace this line in your code

setcookie('remember', $value, $expire, '/', $_SERVER['SERVER_NAME'], true);

with this one:

setcookie('remember', $value, $expire, '/', $_SERVER['SERVER_NAME'], true, true);

For more details read the manual setcookie

answered Feb 15, 2018 at 12:28
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.