3
\$\begingroup\$

I'm trying to make a safe "remember me / auto login" function on my site and as I'm just a hobby programmer I would like someone professional to take a look at my code this far. This site will probably never see the light of day I'm just doing this because I find it fun and learning, but I still like to do it correct. I have read this.

Login.php

$query = $db->prepare('SELECT id, username, password FROM users WHERE username = ? OR email = ?');
$query->execute(array($_POST['username'], $_POST['username']));
$row = $query->fetch();
if ($row and password_verify($_POST['password'], $row['password'])) {
 // Remember?
 if (isset($_POST['remember'])) {
 $selector = base64_encode(random_bytes(9));
 $authenticator = random_bytes(33);
 setcookie('remember', $selector.':'.base64_encode($authenticator), time() + 864000);
 $query = $db->prepare('INSERT INTO auth_tokens (selector, token, userid, expires) VALUES (?, ?, ?, ?)');
 $query->execute(array( $selector, hash('sha256', $authenticator), $row['id'], date('Y-m-d\TH:i:s', time() + 864000) )); 
 }
 $_SESSION['userid'] = $row['id'];
 $_SESSION['username'] = $row['username'];
 exit(header('Location: /'));
}

This is my logout:

session_destroy();
if (!empty($_COOKIE['remember'])) {
 setcookie('remember', '', time() - 1000);
 $db->exec('DELETE FROM auth_tokens WHERE userid = '.$_SESSION['userid']);
}
exit(header('Location: '.SITE_URL));

And this is my code in index.php to check if the user has the cookie and log them in:

if (empty($_SESSION['userid']) && !empty($_COOKIE['remember'])) {
 list($selector, $authenticator) = explode(':', $_COOKIE['remember']);
 $query = $db->prepare('SELECT * FROM auth_tokens WHERE selector = ?');
 $query->execute(array($selector));
 $row = $query->fetch();
 if (hash_equals($row['token'], hash('sha256', base64_decode($authenticator)))) {
 $_SESSION['userid'] = $row['userid'];
 }
}

One thing I need to do is check if the cookie has expired and log them out, but other than that what do you think? Am I missing something?

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Feb 5, 2017 at 15:22
\$\endgroup\$
1
  • \$\begingroup\$ also, i should probably check if the row exists is auth_tokens. in the last code I posted. because if i were to truncate auth_tokens and some users still have the cookie an error will display about hash_equals \$\endgroup\$ Commented Feb 5, 2017 at 15:42

2 Answers 2

2
\$\begingroup\$

You are doing good. You are referencing a good example. The flow will be as below:

  1. Once the user logs in and have checked "remember me", set the cookie with a unique token for user.

  2. Next time when the user comes back, check the cookie with the token value in DB.

  3. If it matches, allow the user to login.

  4. If the token is missing redirect to login.

Ref: http://jaspan.com/improved_persistent_login_cookie_best_practice

Toby Speight
87.2k14 gold badges104 silver badges322 bronze badges
answered Jun 8, 2017 at 7:27
\$\endgroup\$
0
\$\begingroup\$

When a user somehow gets to know your selector and uses it but the token doesn't match, then you need to delete the data in "token" field

Because, if someone else is trying to access in your account with the correct selector but with wrong token then, your account will be immediately secured....

answered Feb 6, 2017 at 19:05
\$\endgroup\$

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.