agent foundation
This commit is contained in:
@@ -3,11 +3,13 @@
|
||||
namespace MintyPHP\Service\Auth;
|
||||
|
||||
use MintyPHP\Auth;
|
||||
use MintyPHP\Http\CookieStoreInterface;
|
||||
use MintyPHP\I18n;
|
||||
use MintyPHP\Http\RequestRuntimeInterface;
|
||||
use MintyPHP\Http\SessionStoreInterface;
|
||||
use MintyPHP\Repository\Auth\RememberTokenRepositoryInterface;
|
||||
use MintyPHP\Repository\User\UserReadRepositoryInterface;
|
||||
use MintyPHP\Repository\User\UserWriteRepositoryInterface;
|
||||
use MintyPHP\Service\User\UserTenantContextService;
|
||||
use MintyPHP\Session;
|
||||
|
||||
class RememberMeService
|
||||
@@ -19,9 +21,11 @@ class RememberMeService
|
||||
private readonly UserReadRepositoryInterface $userReadRepository,
|
||||
private readonly UserWriteRepositoryInterface $userWriteRepository,
|
||||
private readonly RememberTokenRepositoryInterface $rememberTokenRepository,
|
||||
private readonly UserTenantContextService $userTenantContextService,
|
||||
private readonly AuthPermissionGateway $permissionGateway,
|
||||
private readonly AuthSavedFilterGateway $savedFilterGateway
|
||||
private readonly AuthSessionTenantContextService $authSessionTenantContextService,
|
||||
private readonly SessionStoreInterface $sessionStore,
|
||||
private readonly CookieStoreInterface $cookieStore,
|
||||
private readonly RequestRuntimeInterface $requestRuntime
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -37,10 +41,11 @@ class RememberMeService
|
||||
|
||||
public function autoLoginFromCookie(): bool
|
||||
{
|
||||
if (!empty($_SESSION['user']['id'])) {
|
||||
$sessionUser = $this->sessionStore->get('user', []);
|
||||
if (is_array($sessionUser) && !empty($sessionUser['id'])) {
|
||||
return false;
|
||||
}
|
||||
$value = $_COOKIE[$this->cookieName()] ?? '';
|
||||
$value = $this->cookieStore->get($this->cookieName());
|
||||
if ($value === '' || strpos($value, ':') === false) {
|
||||
return false;
|
||||
}
|
||||
@@ -86,15 +91,15 @@ class RememberMeService
|
||||
}
|
||||
|
||||
Session::regenerate();
|
||||
$_SESSION['user'] = $user;
|
||||
$this->sessionStore->set('user', $user);
|
||||
if (!empty($user['locale'])) {
|
||||
I18n::$locale = (string) $user['locale'];
|
||||
}
|
||||
$userId = (int) $user['id'];
|
||||
if ($userId > 0) {
|
||||
$this->permissionGateway->warmUserPermissions($userId, true);
|
||||
$this->loadTenantDataIntoSession($userId);
|
||||
if (!empty($_SESSION['no_active_tenant'])) {
|
||||
$this->authSessionTenantContextService->hydrateForUser($userId);
|
||||
if ((bool) $this->sessionStore->get('no_active_tenant', false)) {
|
||||
// Enforce the same tenant policy as interactive login.
|
||||
$this->forgetCurrentUser();
|
||||
Auth::logout();
|
||||
@@ -103,6 +108,7 @@ class RememberMeService
|
||||
$this->userWriteRepository->updateLastLogin($userId, 'local');
|
||||
}
|
||||
|
||||
// Rotate token on each auto-login — limits the window if a cookie is stolen.
|
||||
$newToken = bin2hex(random_bytes(32));
|
||||
$newHash = hash('sha256', $newToken);
|
||||
$newExpires = gmdate('Y-m-d H:i:s', time() + $this->lifetimeSeconds());
|
||||
@@ -114,7 +120,7 @@ class RememberMeService
|
||||
|
||||
public function forgetCurrentUser(): void
|
||||
{
|
||||
$value = $_COOKIE[$this->cookieName()] ?? '';
|
||||
$value = $this->cookieStore->get($this->cookieName());
|
||||
if ($value !== '' && strpos($value, ':') !== false) {
|
||||
[$selector] = explode(':', $value, 2);
|
||||
$selector = trim($selector);
|
||||
@@ -142,10 +148,9 @@ class RememberMeService
|
||||
{
|
||||
$value = $selector . ':' . $token;
|
||||
$expires = time() + $this->lifetimeSeconds();
|
||||
$secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
|
||||
|| (($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https');
|
||||
$secure = $this->requestRuntime->isSecure();
|
||||
|
||||
setcookie($this->cookieName(), $value, [
|
||||
$this->cookieStore->set($this->cookieName(), $value, [
|
||||
'expires' => $expires,
|
||||
'path' => '/',
|
||||
'secure' => $secure,
|
||||
@@ -156,10 +161,8 @@ class RememberMeService
|
||||
|
||||
private function clearCookie(): void
|
||||
{
|
||||
$secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
|
||||
|| (($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https');
|
||||
setcookie($this->cookieName(), '', [
|
||||
'expires' => time() - 3600,
|
||||
$secure = $this->requestRuntime->isSecure();
|
||||
$this->cookieStore->remove($this->cookieName(), [
|
||||
'path' => '/',
|
||||
'secure' => $secure,
|
||||
'httponly' => true,
|
||||
@@ -178,30 +181,4 @@ class RememberMeService
|
||||
return trim($name) !== '' ? $name : self::COOKIE_NAME;
|
||||
}
|
||||
|
||||
private function loadTenantDataIntoSession(int $userId): void
|
||||
{
|
||||
if ($userId <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$availableTenants = $this->userTenantContextService->getAvailableTenants($userId);
|
||||
$_SESSION['available_tenants'] = $availableTenants;
|
||||
$_SESSION['available_departments_by_tenant'] = $this->userTenantContextService->getAvailableDepartmentsByTenant($userId);
|
||||
$_SESSION['address_book_saved_filters'] = $this->savedFilterGateway->listAddressBookFilters($userId);
|
||||
|
||||
if (!$availableTenants) {
|
||||
$_SESSION['no_active_tenant'] = true;
|
||||
unset($_SESSION['current_tenant']);
|
||||
return;
|
||||
}
|
||||
$_SESSION['no_active_tenant'] = false;
|
||||
|
||||
$currentTenant = $this->userTenantContextService->getCurrentTenant($userId);
|
||||
if (!$currentTenant) {
|
||||
$currentTenant = $availableTenants[0];
|
||||
}
|
||||
if ($currentTenant) {
|
||||
$_SESSION['current_tenant'] = $currentTenant;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user