Working on login system and trying to implement remember me feature.
Recently, l did research about this subject, read bunch of articles, posts, stories, novels, fairy tales (calling them so, because some of them doesn't contain even 1 line of code, just loads of words) about, cookie vulnerabilities such as fixation, hijacking ... etc.
And decided to achieve following targets
But I really confused about my main problem: which way is proper, for "remember me" feature? to use cookies/session/database?
And please explain your idea on code.(I can't understand clearly without code)
Currently, my code looks like that
During sign-in I'm using following function to set cookies and session
protected function validateUser($userid, $ckey=0, $rememmber=0) {
session_start();
session_regenerate_id(true); //this is a security measure
$_SESSION['user_id'] = $userid;
$_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);
if (isset($remember) && $rememmber == 'on') {
setcookie("user_id", $_SESSION['user_id'], time() + 60 * 60 * 24 * COOKIE_TIME_OUT, "/");
setcookie("user_key", sha1($ckey), time() + 60 * 60 * 24 * COOKIE_TIME_OUT, "/");
}
return true;
}
Then on secure user pages, checking for user_id
using user_id to fetch all important data about user from db
public function protect() {
session_start();
/* Secure against Session Hijacking by checking user agent */
if (isset($_SESSION['HTTP_USER_AGENT'])) {
if ($_SESSION['HTTP_USER_AGENT'] != md5($_SERVER['HTTP_USER_AGENT'])) {
$this->signout();
exit;
}
}
// before we allow sessions, we need to check authentication key - ckey and ctime stored in database
/* If session not set, check for cookies set by Remember me */
if (!isset($_SESSION['user_id'])) {
if (isset($_COOKIE['user_id']) && isset($_COOKIE['user_key'])) {
/* we double check cookie expiry time against stored in database */
$cookie_user_id = $_COOKIE['user_id'];
$stmt = $this->db->prepare("select `ckey`,`ctime` from `users` where `id` =?") or die($this->db->error);
$stmt->bind_param("i", $cookie_user_id) or die(htmlspecialchars($stmt->error));
$stmt->execute() or die(htmlspecialchars($stmt->error));
$stmt->bind_result($ckey, $ctime) or die($stmt->error);
$stmt->close() or die(htmlspecialchars($stmt->error));
// coookie expiry
if ((time() - $ctime) > 60 * 60 * 24 * COOKIE_TIME_OUT) {
$this->signout();
}
/* Security check with untrusted cookies - dont trust value stored in cookie.
/* We also do authentication check of the `ckey` stored in cookie matches that stored in database during login */
if (!empty($ckey) && is_numeric($_COOKIE['user_id']) && $_COOKIE['key'] == sha1($ckey)) {
session_regenerate_id(); //against session fixation attacks.
$_SESSION['user_id'] = $_COOKIE['user_id'];
$_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);
} else {
$this->signout();
}
} else {
if ($page != 'main') {
header('Location:' . wsurl);
exit();
}
}
}
It means that if the users access the web application later, they need to log in again. The remember me feature allows the users to save their logins for some time, even after closing the web browsers. To implement the remember me feature, you'll use cookies with expiration times in the future.
Information. Clicking the “Remember Me” box tells the browser to save a cookie so that if you close out the window for the site without signing out, the next time you go back, you will be signed back in automatically. Make sure that you have your browser set to remember cookies, or this function will not work.
In the login form, we will have two input fields (username and password), one checkbox (remember me) and a submit button. Use this link as an outbound link in the article. After the user enters the username, password and select remember me checkbox, the form will look like the following.
Laravel authentication offers remember me functionality out of the box. In order to use it you need to do 2 things: add remember_token column in your users table - this is where the token will be stored. pass true as a second parameter of Auth::attempt() to enable remember me behaviour.
To set time delay between login attempts (to prevent bruteforce attacks) and to limit attempts count
So you're providing a method for DOS by account?
To regenerate session id on nearly every operation
erm, no. That's actually likely to defeat the object. You should always generate a new id when the current id is expired or when the user is authenticated - otherwise leave it alone.
But I really confused about my main problem: which way is proper, for "remember me" feature? to use cookies/session/database?
Since you need to retain a token on the client, that means cookies (unless you fancy writing something really complicated using local storage). Since you don't want to expose data via the cookie / make forgery simple that means it should be a random value. And in order to reconcile the stored random value, that means storing data serverside - probably in a database since it must be possible to reference the data based on the user id or based on the random value.
While you could just use a non-expiring (or very long lived) session, I'd stay away from this - the data will snowball - and it's a good idea to renew the session data once in a while.
You also need to cater for the scenario where a user wants you to remember her on 2 different computers. If you only hold a single 'remember me' token for each account, then either you'll have to use the same value at both clients or delete the old token when you create a new one (i.e. user can only be remembered on one machine).
please explain your idea on code. I can't understand clearly without code
No. I get paid to write code; If you want me to write the code for you then you'll need to pay me. And the code will take up much more space and time than the description above.
If you want an example of a "remember me" function with code, you can check out my PHP library at https://github.com/gbirke/rememberme
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With