mirror of
https://github.com/delight-im/PHP-Auth.git
synced 2025-08-04 07:07:25 +02:00
Store and manage 'force_logout' value from 'users' table in session
This commit is contained in:
@@ -558,7 +558,7 @@ final class Administration extends UserManager {
|
||||
$user = $users[0];
|
||||
|
||||
if ((int) $user['verified'] === 1) {
|
||||
$this->onLoginSuccessful($user['id'], $user['email'], $user['username'], $user['status'], $user['roles_mask'], false);
|
||||
$this->onLoginSuccessful($user['id'], $user['email'], $user['username'], $user['status'], $user['roles_mask'], \PHP_INT_MAX, false);
|
||||
}
|
||||
else {
|
||||
throw new EmailNotVerifiedException();
|
||||
|
17
src/Auth.php
17
src/Auth.php
@@ -114,7 +114,7 @@ final class Auth extends UserManager {
|
||||
if (!empty($parts[0]) && !empty($parts[1])) {
|
||||
try {
|
||||
$rememberData = $this->db->selectRow(
|
||||
'SELECT a.user, a.token, a.expires, b.email, b.username, b.status, b.roles_mask FROM ' . $this->dbTablePrefix . 'users_remembered AS a JOIN ' . $this->dbTablePrefix . 'users AS b ON a.user = b.id WHERE a.selector = ?',
|
||||
'SELECT a.user, a.token, a.expires, b.email, b.username, b.status, b.roles_mask, b.force_logout FROM ' . $this->dbTablePrefix . 'users_remembered AS a JOIN ' . $this->dbTablePrefix . 'users AS b ON a.user = b.id WHERE a.selector = ?',
|
||||
[ $parts[0] ]
|
||||
);
|
||||
}
|
||||
@@ -128,7 +128,7 @@ final class Auth extends UserManager {
|
||||
// the cookie and its contents have now been proven to be valid
|
||||
$valid = true;
|
||||
|
||||
$this->onLoginSuccessful($rememberData['user'], $rememberData['email'], $rememberData['username'], $rememberData['status'], $rememberData['roles_mask'], true);
|
||||
$this->onLoginSuccessful($rememberData['user'], $rememberData['email'], $rememberData['username'], $rememberData['status'], $rememberData['roles_mask'], $rememberData['force_logout'], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -392,6 +392,7 @@ final class Auth extends UserManager {
|
||||
unset($_SESSION[self::SESSION_FIELD_ROLES]);
|
||||
unset($_SESSION[self::SESSION_FIELD_REMEMBERED]);
|
||||
unset($_SESSION[self::SESSION_FIELD_LAST_RESYNC]);
|
||||
unset($_SESSION[self::SESSION_FIELD_FORCE_LOGOUT]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,7 +491,7 @@ final class Auth extends UserManager {
|
||||
}
|
||||
}
|
||||
|
||||
protected function onLoginSuccessful($userId, $email, $username, $status, $roles, $remembered) {
|
||||
protected function onLoginSuccessful($userId, $email, $username, $status, $roles, $forceLogout, $remembered) {
|
||||
// update the timestamp of the user's last login
|
||||
try {
|
||||
$this->db->update(
|
||||
@@ -503,7 +504,7 @@ final class Auth extends UserManager {
|
||||
throw new DatabaseError();
|
||||
}
|
||||
|
||||
parent::onLoginSuccessful($userId, $email, $username, $status, $roles, $remembered);
|
||||
parent::onLoginSuccessful($userId, $email, $username, $status, $roles, $forceLogout, $remembered);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -659,10 +660,10 @@ final class Auth extends UserManager {
|
||||
|
||||
$userData = $this->getUserDataByEmailAddress(
|
||||
$verifiedEmail,
|
||||
[ 'id', 'email', 'username', 'status', 'roles_mask' ]
|
||||
[ 'id', 'email', 'username', 'status', 'roles_mask', 'force_logout' ]
|
||||
);
|
||||
|
||||
$this->onLoginSuccessful($userData['id'], $userData['email'], $userData['username'], $userData['status'], $userData['roles_mask'], true);
|
||||
$this->onLoginSuccessful($userData['id'], $userData['email'], $userData['username'], $userData['status'], $userData['roles_mask'], $userData['force_logout'], true);
|
||||
|
||||
if ($rememberDuration !== null) {
|
||||
$this->createRememberDirective($userData['id'], $rememberDuration);
|
||||
@@ -958,7 +959,7 @@ final class Auth extends UserManager {
|
||||
$this->throttle([ 'enumerateUsers', $this->getIpAddress() ], 1, (60 * 60), 75);
|
||||
$this->throttle([ 'attemptToLogin', $this->getIpAddress() ], 4, (60 * 60), 5, true);
|
||||
|
||||
$columnsToFetch = [ 'id', 'email', 'password', 'verified', 'username', 'status', 'roles_mask' ];
|
||||
$columnsToFetch = [ 'id', 'email', 'password', 'verified', 'username', 'status', 'roles_mask', 'force_logout' ];
|
||||
|
||||
if ($email !== null) {
|
||||
$email = self::validateEmailAddress($email);
|
||||
@@ -995,7 +996,7 @@ final class Auth extends UserManager {
|
||||
|
||||
if ((int) $userData['verified'] === 1) {
|
||||
if (!isset($onBeforeSuccess) || (\is_callable($onBeforeSuccess) && $onBeforeSuccess($userData['id']) === true)) {
|
||||
$this->onLoginSuccessful($userData['id'], $userData['email'], $userData['username'], $userData['status'], $userData['roles_mask'], false);
|
||||
$this->onLoginSuccessful($userData['id'], $userData['email'], $userData['username'], $userData['status'], $userData['roles_mask'], $userData['force_logout'], false);
|
||||
|
||||
// continue to support the old parameter format
|
||||
if ($rememberDuration === true) {
|
||||
|
@@ -40,6 +40,8 @@ abstract class UserManager {
|
||||
const SESSION_FIELD_REMEMBERED = 'auth_remembered';
|
||||
/** @var string session field for the UNIX timestamp in seconds of the session data's last resynchronization with its authoritative source in the database */
|
||||
const SESSION_FIELD_LAST_RESYNC = 'auth_last_resync';
|
||||
/** @var string session field for the counter that keeps track of forced logouts that need to be performed in the current session */
|
||||
const SESSION_FIELD_FORCE_LOGOUT = 'auth_force_logout';
|
||||
|
||||
/** @var PdoDatabase the database connection to operate on */
|
||||
protected $db;
|
||||
@@ -219,10 +221,11 @@ abstract class UserManager {
|
||||
* @param string $username the display name (if any) of the user
|
||||
* @param int $status the status of the user as one of the constants from the {@see Status} class
|
||||
* @param int $roles the roles of the user as a bitmask using constants from the {@see Role} class
|
||||
* @param int $forceLogout the counter that keeps track of forced logouts that need to be performed in the current session
|
||||
* @param bool $remembered whether the user has been remembered (instead of them having authenticated actively)
|
||||
* @throws AuthError if an internal problem occurred (do *not* catch)
|
||||
*/
|
||||
protected function onLoginSuccessful($userId, $email, $username, $status, $roles, $remembered) {
|
||||
protected function onLoginSuccessful($userId, $email, $username, $status, $roles, $forceLogout, $remembered) {
|
||||
// re-generate the session ID to prevent session fixation attacks (requests a cookie to be written on the client)
|
||||
Session::regenerate(true);
|
||||
|
||||
@@ -235,6 +238,7 @@ abstract class UserManager {
|
||||
$_SESSION[self::SESSION_FIELD_ROLES] = (int) $roles;
|
||||
$_SESSION[self::SESSION_FIELD_REMEMBERED] = $remembered;
|
||||
$_SESSION[self::SESSION_FIELD_LAST_RESYNC] = \time();
|
||||
$_SESSION[self::SESSION_FIELD_FORCE_LOGOUT] = (int) $forceLogout;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user