vespula / remember-me
A simple PHP package for managing persistent 'remember me' authentication using secure cookies and database-backed tokens.
Requires
- php: >=8.3
Requires (Dev)
- ext-sqlite3: *
- phpunit/phpunit: 12.5.*
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-06 20:50:31 UTC
README
A simple package for managing remember-me cookies and validating their tokens against a database. A random token is generated and stored in a cookie. A hashed value of the token is then stored in the database along with a creation date and an expiry date. A cookie can only be valid if it matches the record in the database and is not expired.
This package does not perform user authentication or manage sessions. It works alongside an application's existing authentication system to provide persistent login functionality.
This package consists of 4 classes:
A Service
- sets the cookie and token if they don't exist
- validates the cookie and token, if they exist
- removes expired tokens and expires their associated cookies
- removes the cookie and token when logging out
A Token
- represents a token object and holds its values
A Repository
- is responsible for interacting with the database
A Cookie
- sets the cookie in the browser
- expires the cookie effectively deleting it from the browser
Installation
composer require vespula/remember-me
You will also need a table in your database. The default table name is remember_me_tokens, but this can be configured in the Repository. A sample create table SQL is included (using MySQL), and also shown below:
CREATE TABLE `remember_me_tokens` (
`id` int NOT NULL AUTO_INCREMENT,
`userid` varchar(255) NOT NULL,
`token_hash` varchar(64) NOT NULL,
`expires_at` datetime NOT NULL,
`created_at` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `token_hash` (`token_hash`),
KEY `userid` (`userid`),
KEY `expires_at` (`expires_at`)
)
If you use phinx for managing migrations, a simple migration to create the table is below:
<?php
$table = $this->table('remember_me_tokens');
$table->addColumn('userid', 'string', ['null'=>false])
->addColumn('token_hash', 'string', ['null'=>false, 'length'=>64])
->addColumn('created_at', 'datetime', ['null'=>false])
->addColumn('expires_at', 'datetime', ['null'=>false])
->addIndex('userid')
->addIndex('token_hash', ['unique'=>true])
->addIndex('expires_at')
->create();
Usage
The basic set up requires a Remember Me Service object
<?php
use PDO;
use Vespula\RememberMe\Cookie;
use Vespula\RememberMe\Repository;
use Vespula\RememberMe\Service;
$pdo = new \PDO("mysql:dbname=mydb;host=127.0.0.1", 'juser', '******');
// These are the defaults and are not required. You can override as required.
$cookie_options = [
'secure'=>true,
'httpOnly'=>true,
'samesite'=>'Lax'
];
$expiry_days = 20; // default is 30
$cookie_name = 'vespula_remember_me';
$table_name = 'my_remember_tokens'; // default is remember_me_tokens
$rememberMeCookie = new Cookie($cookie_name, $cookie_options);
$rememberMeRepository = new Repository($pdo, $table_name);
$rememberMeService = new Service($rememberMeRepository, $rememberMeCookie, $expiry_days);
When the user logs in and has checked the "remember me" checkbox.
<?php
$doRememberMe = true; // from the checkbox
// Login using your authentication library
$auth->login([
'username'=>$username,
'password'=>$password
]);
if ($auth->isValid()) {
if ($doRememberMe === true) {
// Create the cookie and insert a token record into the database
$rememberMeService->createToken($username);
}
// do other stuff...
}
When a user logs out, explicitly revoke their remember-me token and expire the remember-me cookie.
<?php
// User clicks the logout button or link...
$auth->logout();
// If using PSR-7 requests...
$cookies = $request->getCookieParams();
// Or
$cookies = $_COOKIE;
$rememberMeService->forget($cookies);
// etc.
When a user visits your site, check the state of authentication. If they are logged in, proceed as normal. If not, check and validate a remember me cookie. Validating the cookie includes checking expiry and validating it against the token stored in the database. On successful validation, the token is rotated so that the previously presented token cannot be reused.
<?php
if (! $auth->isValid()) {
// How you get the rememberMeService is up to you. I use a container/registry.
$cookies = $request->getCookieParams();
// or if not PSR-7
$cookies = $_COOKIE;
$rememberMeToken = $rememberMeService->validateCookie($cookies);
if ($rememberMeToken !== null) {
// Autologin
$credentials = [
'username'=>$rememberMeToken->getUserid(),
'password'=>null,
];
$auth->autoLogin($credentials);
}
}