mirror of
https://github.com/delight-im/PHP-Auth.git
synced 2025-08-04 15:17:28 +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];
|
$user = $users[0];
|
||||||
|
|
||||||
if ((int) $user['verified'] === 1) {
|
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 {
|
else {
|
||||||
throw new EmailNotVerifiedException();
|
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])) {
|
if (!empty($parts[0]) && !empty($parts[1])) {
|
||||||
try {
|
try {
|
||||||
$rememberData = $this->db->selectRow(
|
$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] ]
|
[ $parts[0] ]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -128,7 +128,7 @@ final class Auth extends UserManager {
|
|||||||
// the cookie and its contents have now been proven to be valid
|
// the cookie and its contents have now been proven to be valid
|
||||||
$valid = true;
|
$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_ROLES]);
|
||||||
unset($_SESSION[self::SESSION_FIELD_REMEMBERED]);
|
unset($_SESSION[self::SESSION_FIELD_REMEMBERED]);
|
||||||
unset($_SESSION[self::SESSION_FIELD_LAST_RESYNC]);
|
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
|
// update the timestamp of the user's last login
|
||||||
try {
|
try {
|
||||||
$this->db->update(
|
$this->db->update(
|
||||||
@@ -503,7 +504,7 @@ final class Auth extends UserManager {
|
|||||||
throw new DatabaseError();
|
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(
|
$userData = $this->getUserDataByEmailAddress(
|
||||||
$verifiedEmail,
|
$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) {
|
if ($rememberDuration !== null) {
|
||||||
$this->createRememberDirective($userData['id'], $rememberDuration);
|
$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([ 'enumerateUsers', $this->getIpAddress() ], 1, (60 * 60), 75);
|
||||||
$this->throttle([ 'attemptToLogin', $this->getIpAddress() ], 4, (60 * 60), 5, true);
|
$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) {
|
if ($email !== null) {
|
||||||
$email = self::validateEmailAddress($email);
|
$email = self::validateEmailAddress($email);
|
||||||
@@ -995,7 +996,7 @@ final class Auth extends UserManager {
|
|||||||
|
|
||||||
if ((int) $userData['verified'] === 1) {
|
if ((int) $userData['verified'] === 1) {
|
||||||
if (!isset($onBeforeSuccess) || (\is_callable($onBeforeSuccess) && $onBeforeSuccess($userData['id']) === true)) {
|
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
|
// continue to support the old parameter format
|
||||||
if ($rememberDuration === true) {
|
if ($rememberDuration === true) {
|
||||||
|
@@ -40,6 +40,8 @@ abstract class UserManager {
|
|||||||
const SESSION_FIELD_REMEMBERED = 'auth_remembered';
|
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 */
|
/** @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';
|
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 */
|
/** @var PdoDatabase the database connection to operate on */
|
||||||
protected $db;
|
protected $db;
|
||||||
@@ -219,10 +221,11 @@ abstract class UserManager {
|
|||||||
* @param string $username the display name (if any) of the user
|
* @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 $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 $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)
|
* @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)
|
* @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)
|
// re-generate the session ID to prevent session fixation attacks (requests a cookie to be written on the client)
|
||||||
Session::regenerate(true);
|
Session::regenerate(true);
|
||||||
|
|
||||||
@@ -235,6 +238,7 @@ abstract class UserManager {
|
|||||||
$_SESSION[self::SESSION_FIELD_ROLES] = (int) $roles;
|
$_SESSION[self::SESSION_FIELD_ROLES] = (int) $roles;
|
||||||
$_SESSION[self::SESSION_FIELD_REMEMBERED] = $remembered;
|
$_SESSION[self::SESSION_FIELD_REMEMBERED] = $remembered;
|
||||||
$_SESSION[self::SESSION_FIELD_LAST_RESYNC] = \time();
|
$_SESSION[self::SESSION_FIELD_LAST_RESYNC] = \time();
|
||||||
|
$_SESSION[self::SESSION_FIELD_FORCE_LOGOUT] = (int) $forceLogout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user