| <?php |
|
|
| |
| |
| |
| |
| |
| |
|
|
| namespace Piwik\Session; |
|
|
| use Piwik\Auth; |
| use Piwik\AuthResult; |
| use Piwik\Config; |
| use Piwik\Container\StaticContainer; |
| use Piwik\Date; |
| use Piwik\Plugins\UsersManager\Model as UsersModel; |
| use Piwik\Session; |
| use Piwik\Log\LoggerInterface; |
|
|
| |
| |
| |
| |
| |
| class SessionAuth implements Auth |
| { |
| |
| |
| |
| |
| |
| private $shouldDestroySession; |
|
|
| |
| |
| |
| private $userModel; |
|
|
| |
| |
| |
| |
| |
| private $user; |
|
|
| private $tokenAuth; |
|
|
| |
| |
| |
| private $sessionExpired = false; |
|
|
| public function __construct(?UsersModel $userModel = null, $shouldDestroySession = true) |
| { |
| $this->userModel = $userModel ?: new UsersModel(); |
| $this->shouldDestroySession = $shouldDestroySession; |
| } |
|
|
| public function getName() |
| { |
| return null; |
| } |
|
|
| public function setTokenAuth( |
| #[\SensitiveParameter] |
| $token_auth |
| ) { |
| $this->tokenAuth = $token_auth; |
| } |
|
|
| public function getLogin() |
| { |
| if (isset($this->user['login'])) { |
| return $this->user['login']; |
| } |
|
|
| return null; |
| } |
|
|
| public function getTokenAuthSecret() |
| { |
| return null; |
| } |
|
|
| public function setLogin($login) |
| { |
| |
| } |
|
|
| public function setPassword( |
| #[\SensitiveParameter] |
| $password |
| ) { |
| |
| } |
|
|
| public function setPasswordHash( |
| #[\SensitiveParameter] |
| $passwordHash |
| ) { |
| |
| } |
|
|
| public function authenticate() |
| { |
| $this->sessionExpired = false; |
| $sessionFingerprint = new SessionFingerprint(); |
| $userModel = $this->userModel; |
|
|
| $this->checkIfSessionFailedToRead(); |
|
|
| if ($this->isExpiredSession($sessionFingerprint)) { |
| $sessionFingerprint->clear(); |
| return $this->makeAuthFailure(); |
| } |
|
|
| $userForSession = $sessionFingerprint->getUser(); |
| if (empty($userForSession)) { |
| return $this->makeAuthFailure(); |
| } |
|
|
| $user = $userModel->getUser($userForSession); |
| if ( |
| empty($user) |
| || $user['login'] !== $userForSession |
| ) { |
| return $this->makeAuthFailure(); |
| } |
|
|
| $tsPasswordModified = !empty($user['ts_password_modified']) ? $user['ts_password_modified'] : null; |
| if ($this->isSessionStartedBeforePasswordChange($sessionFingerprint, $tsPasswordModified)) { |
| $this->destroyCurrentSession($sessionFingerprint); |
| return $this->makeAuthFailure(); |
| } |
|
|
| $this->updateSessionExpireTime($sessionFingerprint); |
|
|
| if ( |
| $this->tokenAuth !== null |
| && $this->tokenAuth !== false |
| && $this->tokenAuth !== $sessionFingerprint->getSessionTokenAuth() |
| ) { |
| return $this->makeAuthFailure(); |
| } |
|
|
| if ($sessionFingerprint->getSessionTokenAuth()) { |
| $tokenAuth = $sessionFingerprint->getSessionTokenAuth(); |
| } else { |
| $tokenAuth = $this->userModel->generateRandomTokenAuth(); |
| } |
|
|
| return $this->makeAuthSuccess($user, $tokenAuth); |
| } |
|
|
| private function isSessionStartedBeforePasswordChange(SessionFingerprint $sessionFingerprint, $tsPasswordModified) |
| { |
| |
| if ($tsPasswordModified === null) { |
| return false; |
| } |
|
|
| |
| $sessionStartTime = $sessionFingerprint->getSessionStartTime(); |
| if (empty($sessionStartTime)) { |
| return true; |
| } |
|
|
| return $sessionStartTime < Date::factory($tsPasswordModified)->getTimestampUTC(); |
| } |
|
|
| private function makeAuthFailure() |
| { |
| return new AuthResult(AuthResult::FAILURE, null, null); |
| } |
|
|
| private function makeAuthSuccess( |
| $user, |
| #[\SensitiveParameter] |
| $tokenAuth |
| ) { |
| $this->user = $user; |
| $this->tokenAuth = $tokenAuth; |
|
|
| $isSuperUser = (int) $user['superuser_access']; |
| $code = $isSuperUser ? AuthResult::SUCCESS_SUPERUSER_AUTH_CODE : AuthResult::SUCCESS; |
|
|
| return new AuthResult($code, $user['login'], $tokenAuth); |
| } |
|
|
| protected function initNewBlankSession(SessionFingerprint $sessionFingerprint) |
| { |
| |
| |
| |
| if ($this->shouldDestroySession) { |
| session_regenerate_id(); |
| } |
|
|
| |
| |
| |
| $sessionFingerprint->clear(); |
| } |
|
|
| protected function destroyCurrentSession(SessionFingerprint $sessionFingerprint) |
| { |
| |
| |
| |
| |
| |
| |
| $sessionFingerprint->clear(); |
| if ($this->shouldDestroySession) { |
| Session::regenerateId(); |
| } |
| } |
|
|
| public function getTokenAuth() |
| { |
| return $this->tokenAuth; |
| } |
|
|
| private function updateSessionExpireTime(SessionFingerprint $sessionFingerprint) |
| { |
| $sessionParams = session_get_cookie_params(); |
|
|
| |
| $sessionCookieLifetime = Config::getInstance()->General['login_cookie_expire']; |
| Session::writeCookie( |
| session_name(), |
| session_id(), |
| time() + $sessionCookieLifetime, |
| $sessionParams['path'], |
| $sessionParams['domain'], |
| $sessionParams['secure'], |
| $sessionParams['httponly'], |
| Session::getSameSiteCookieValue() |
| ); |
|
|
| |
| $sessionFingerprint->updateSessionExpirationTime(); |
| } |
|
|
| private function isExpiredSession(SessionFingerprint $sessionFingerprint) |
| { |
| $expirationTime = $sessionFingerprint->getExpirationTime(); |
| if (empty($expirationTime)) { |
| return true; |
| } |
|
|
| $isExpired = Date::now()->getTimestampUTC() > $expirationTime; |
| if ($isExpired) { |
| $this->sessionExpired = true; |
| } |
| return $isExpired; |
| } |
|
|
| public function wasSessionExpired(): bool |
| { |
| return $this->sessionExpired; |
| } |
|
|
| private function checkIfSessionFailedToRead() |
| { |
| if (Session\SaveHandler\DbTable::$wasSessionToLargeToRead) { |
| StaticContainer::get(LoggerInterface::class)->warning( |
| "Too much data stored in the session so it could not be read properly. If you were logged out, this is why." |
| ); |
| } |
| } |
| } |
|
|