Login system concept & logic?

7.4k views Asked by At

I want to know the process which usually web apps follow to maintain login between multiple requests and also how they manage things using COOKIES.

In my login form I am providing "Remember Me" feature.

When user login then I check the username and password validity from database. If its valid then I check if "Remember me" is selected, if yes then storing username and password in session, encrypted format. And finally storing username and password in SESSION.

When user navigates form one page to another, first I run login check script which checks if there is any value in cookies, then it validates that username and password from database, to check its validity. If there is no value in cookie and there is some value in session, then I am fetching session value an dnot checking it from db.

I am not checking session value form db to not hit db unnecessarily, speed up the things. In case of cookies, they can be modified, so check is needed.

This is what my concept, is it right? Is it the way to go and normally website slike SO, and other works on this kind of method?

Or websites check login authenticity on each page load, no matters its in session or in cookies?

Please check and give your thoughts and concepts for this scenario.

Thanks!

1

There are 1 answers

5
Carlos Campderrós On BEST ANSWER

First, just track if someone is logged in. After that, we'll take care of the "remember me" feature.

To know if there's someone logged in, you just look at the $_SESSION array. Everything that's in there is because you put it there before. So, when processing a login form, if username & password are correct, then you store the username, user id or whatever at the session ($_SESSION['username'] = $username;).

Whenever the user loads any page, you just check

if (isset($_SESSION['username'])) {
    // $_SESSION['username'] is logged in
} else {
    // nobody is logged in
}

There's no need to store the password in the $_SESSION (in fact, for security purposes, it's better to not store it anywhere except hashed in the database).

Now, the "remember me" feature... First, some considerations:

  • Any user can modify its browser's cookies, so you need to be sure that the cookie sent to the application has been not tampered with.
  • Users may check that at public computers (libraries or so), so you need a system to invalidate that.
  • If a user logs out of your application, the cookie remembering him/her must be erased.

For the first point, imagine that on the cookie you store the username of the user to be "remembered" (VERY INSECURE!!). That means that if any user creates a cookie for you web application with the content 'joe', your app will think that user joe is remembered in that computer so grant access to this attacker as if he/she were joe. So, we need to crypt/hash the cookie in some way.

For the second point, invalidating "remember me" at some computers, we'll use the password in some way. If some user wants to invalidate all computers where he/she might have checked the "remember me" checkbox, all he/she has to do is change his/her password. That also means that if he/she changes his/her password, all saved logins for his/her account will be invalidated, for the same exact reason. But better safe than sorry...

So, when you process a login and the username and password is correct, and the "rememeber me" option is checked, in addition to saving the username in the session, you store a hash of the username & password (and some salt if you will) in a cookie you send to the user. Also you need to store in the cookie the username in plain text (or crypted in a reversable way) to know which user is trying to "log in" via cookie, and check the hash of username & password in the cookie with the hash of username & password in the database. If that check is correct, you then store the username in the session and don't check anymore the cookie of this user (at least for this session).

So, overall your code might look like this:

login.php

if (check_login($_POST['username'], $_POST['password'])) {
    // login correct
    $_SESSION['username'] = $_POST['username'];
    if (isset($_POST['remember_me'])) {
        // we hash the password because we **NEVER** store it in plain text anywhere
        // so when we would like to check if the cookie value is correct, we will not
        // be able to do so if the hash in the cookie was done from the plaintext
        // password.
        $value = sprintf('%s:%s', $_POST['username'], md5($_POST['username'].hash_password($_POST['password'])));
        setcookie('rememberme', $value);
    }
    redirect('/your/home/page.php'); // view Post/Redirect/Get design pattern
} else {
    // login incorrect, show error message and whatever...
}

at beginning of every php file (or better, in a included file to bootstrap your app)

if (isset($_SESSION['username'])) {
    // $_SESSION['username'] is logged in, proceed as you wish
} else if (isset($_COOKIE['rememberme'])) {
    // this user has checked the remember me feature some time ago in a previous login.
    // let's check if it is valid.
    list($username, $hash) = explode(':', $_COOKIE['rememberme']);

    // we need to get the password hash stored for this user (remember you **NEVER** store passwords in plain text
    $pwd_hash = obtain_password_hash_from_username($username);
    if ($hash == sprintf('%s:%s', $username, md5($username.$pwd_hash))) {
        // yeah, the user remembered is correct. We'll save it to the session to not do this shit again
        $_SESSION['username'] = $username;
    } else {
        // the cookie value is not correct so maybe an attacker is trying to fool us,
        // or the user changed his password. Whatever it is, we remove the cookie
        // because it's no longer valid
        setcookie('rememberme', '', time() - 3600);
    }

} else {
    // this user is neither logged in nor "remembered"
}

The method to hash the user password is up to you. You might like plain md5 or sha, salted md5 or sha (better) or some time-consuming method like blowfish (recommended). To hash the cookie I've used plain md5, but you may choose any of the method described early.

I think that's all.