I have seen time and again Charles Miller's "Persistent Login Cookie Best Practice" recommended here as the absolute best way of implementing "Remember me" functionality on a site (if you really, really need that feature, which I do).
However, I've scoured the web and I can't find any actual PHP/MySQL code implementing his solution, and since "security" was stressed about a gazillion times with regard to using "Remember me", I'm afraid to code it myself from scratch for fear that I will misunderstand something or make a mistake that will result in a massive security hole.
Since his solution is almost 10 years old and happens to be the most upvoted answer on SO regarding Persistent Login Cookies, surely there has to be some vetted PHP/MySQL code out there that correctly follows his solution without any unintended security holes. (The closest thing I found was a Drupal module, but I don't use Drupal.)
Does anyone know where I can find it?
After reading a question on StackOverflow I’ve been inspired to help him out by writing a PHP/MySQL implementation of Charles Miller’s “Persistent Login Cookie Best Practice” For this tutorial I’m going to assume you already have a PHP system with user login.
CREATE TABLE user_sessions (
user_id INT(11) UNSIGNED NOT NULL,
session VARCHAR(39) NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
PRIMARY KEY (user_id, session)
);
First, we need to update the site when you login to store the session into the cookie. This code will go with your current login system.
if (/* Code that verifies credentials */) {
// ... code to log user into session
PersistentAuth::login($userId);
}
Second, we want to check if a new user to the site has cookie credentials. This code will go at the beginning of your code. It checks, first, are we already logged in in our $_SESSION? if not, try the cookie-based login.
if (/* !loggedIn() */ && ($userId = PersistentAuth::cookieLogin())) {
// ... use $userId to log user into session
}
Third, in accordance with Charles Miller’s article we cannot allow a user to the following sections if they are logged in via cookie:
- Changing the user’s password
- Changing the user’s email address (especially if email-based password recovery is used)
- Any access to the user’s address, payment details or financial information
- Any ability to make a purchase
Code:
if (PersistentAuth::isCookieLogin()) {
// User is logged in via cookie and don't have access to this
// section. We need to ask them for the password. Maybe send
// them to some login page?
// TODO ask for password or send to a password page
}
To get all the code for the PersistentAuth class checkout my site here: http://www.chrislondon.co/php-persistent-login/
With this PersistentAuth class there are a few changes you will have to make. One you’ll have to change the getDb() function to return an instance of your database. I’m using PDO in this example. I have it set up for every page refresh clear the database of old sessions. The best way to handle this is to use a cron. If you do set up a cron then change the USE_CRON flag to true in the class settings