‪TYPO3CMS  ‪main
UserSession.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
24 
45 {
46  use ‪JwtTrait;
47 
48  protected const ‪SESSION_UPDATE_GRACE_PERIOD = 61;
49  protected string ‪$identifier;
50  protected ?int ‪$userId;
51  protected int ‪$lastUpdated;
52  protected array ‪$data;
53  protected bool ‪$wasUpdated = false;
54  protected string ‪$ipLock = '';
55  protected bool ‪$isNew = true;
56  protected bool ‪$isPermanent = false;
57 
58  protected function ‪__construct(string ‪$identifier, int ‪$userId, int ‪$lastUpdated, array ‪$data = [])
59  {
60  $this->identifier = ‪$identifier;
61  $this->userId = ‪$userId > 0 ? ‪$userId : null;
62  $this->lastUpdated = ‪$lastUpdated;
63  $this->data = ‪$data;
64  }
65 
69  public function ‪getIdentifier(): string
70  {
71  return ‪$this->identifier;
72  }
73 
77  public function ‪getUserId(): ?int
78  {
79  return ‪$this->userId;
80  }
81 
85  public function ‪getLastUpdated(): int
86  {
87  return ‪$this->lastUpdated;
88  }
89 
97  public function set(string $key, $value): void
98  {
99  if ($key === '') {
100  throw new \InvalidArgumentException('Argument key must not be empty', 1484312516);
101  }
102  if ($value === null) {
103  unset($this->data[$key]);
104  } else {
105  $this->data[$key] = $value;
106  }
107  $this->wasUpdated = true;
108  }
109 
113  public function ‪hasData(): bool
114  {
115  return $this->data !== [];
116  }
117 
123  public function get(string $key)
124  {
125  return $this->data[$key] ?? null;
126  }
127 
131  public function ‪getData(): array
132  {
133  return ‪$this->data;
134  }
135 
140  public function ‪overrideData(array ‪$data): void
141  {
142  if ($this->data !== ‪$data) {
143  // Only set update flag if there is change in the $data array
144  $this->wasUpdated = true;
145  }
146 
147  $this->data = ‪$data;
148  }
149 
153  public function ‪dataWasUpdated(): bool
154  {
155  return ‪$this->wasUpdated;
156  }
157 
162  public function ‪isAnonymous(): bool
163  {
164  return $this->userId === 0 || $this->userId === null;
165  }
166 
170  public function ‪getIpLock(): string
171  {
172  return ‪$this->ipLock;
173  }
174 
178  public function ‪isNew(): bool
179  {
180  return ‪$this->isNew;
181  }
182 
186  public function ‪isPermanent(): bool
187  {
188  return ‪$this->isPermanent;
189  }
190 
194  public function ‪needsUpdate(): bool
195  {
196  return ‪$GLOBALS['EXEC_TIME'] > ($this->lastUpdated + ‪self::SESSION_UPDATE_GRACE_PERIOD);
197  }
198 
206  public function ‪getJwt(?CookieScope $scope = null): string
207  {
208  // @todo payload could be organized in a new `SessionToken` object
210  [
211  'identifier' => $this->identifier,
212  'time' => (new \DateTimeImmutable())->format(\DateTimeImmutable::RFC3339),
213  'scope' => $scope,
214  ],
215  self::createSigningKeyFromEncryptionKey(UserSession::class)
216  );
217  }
218 
224  public static function ‪createFromRecord(string $id, array ‪$record, bool $markAsNew = false): self
225  {
226  $userSession = new self(
227  $id,
228  (int)(‪$record['ses_userid'] ?? 0),
229  (int)(‪$record['ses_tstamp'] ?? 0),
230  unserialize(‪$record['ses_data'] ?? '', ['allowed_classes' => false]) ?: []
231  );
232  $userSession->ipLock = ‪$record['ses_iplock'] ?? '';
233  $userSession->isNew = $markAsNew;
234  if (isset(‪$record['ses_permanent'])) {
235  $userSession->isPermanent = (bool)‪$record['ses_permanent'];
236  }
237  return $userSession;
238  }
239 
244  public static function ‪createNonFixated(string ‪$identifier): self
245  {
246  $userSession = new self(‪$identifier, 0, ‪$GLOBALS['EXEC_TIME'], []);
247  $userSession->isPermanent = false;
248  $userSession->isNew = true;
249  return $userSession;
250  }
251 
262  public static function ‪resolveIdentifierFromJwt(string $cookieValue, CookieScope $scope): ?string
263  {
264  if ($cookieValue === '') {
265  return null;
266  }
267 
268  $payload = ‪self::decodeJwt($cookieValue, self::createSigningKeyFromEncryptionKey(UserSession::class));
269 
270  ‪$identifier = !empty($payload->identifier) && is_string($payload->identifier) ? $payload->identifier : null;
271  if (‪$identifier === null) {
272  return null;
273  }
274 
275  $domainScope = (string)($payload->scope->domain ?? '');
276  $pathScope = (string)($payload->scope->path ?? '');
277  if ($domainScope === '' || $pathScope === '') {
278  $logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(self::class);
279  $logger->notice('A session cookie with out a domain scope has been used', ['cookieHash' => substr(sha1($cookieValue), 0, 12)]);
280  return ‪$identifier;
281  }
282  if ($domainScope !== $scope->domain || $pathScope !== $scope->path) {
283  // invalid scope, the cookie jwt has been used on a wrong path or domain
284  return null;
285  }
286 
287  return ‪$identifier;
288  }
289 
294  public function ‪toArray(): array
295  {
296  ‪$data = [
297  'ses_id' => ‪$this->identifier,
298  'ses_data' => serialize($this->data),
299  'ses_userid' => (int)$this->userId,
300  'ses_iplock' => $this->ipLock,
301  'ses_tstamp' => $this->lastUpdated,
302  ];
303  if ($this->‪isPermanent) {
304  $data['ses_permanent'] = 1;
305  }
306  return ‪$data;
307  }
308 }
‪TYPO3\CMS\Core\Security\JwtTrait\decodeJwt
‪static decodeJwt(string $jwt, Key $key, bool $associative=false)
Definition: JwtTrait.php:63
‪TYPO3\CMS\Core\Session\UserSession\isAnonymous
‪isAnonymous()
Definition: UserSession.php:161
‪TYPO3\CMS\Core\Session\UserSession\getIdentifier
‪string getIdentifier()
Definition: UserSession.php:68
‪TYPO3\CMS\Core\Session\UserSession\SESSION_UPDATE_GRACE_PERIOD
‪const SESSION_UPDATE_GRACE_PERIOD
Definition: UserSession.php:47
‪TYPO3\CMS\Core\Session\UserSession\toArray
‪array toArray()
Definition: UserSession.php:293
‪TYPO3\CMS\Core\Session\UserSession\createNonFixated
‪static createNonFixated(string $identifier)
Definition: UserSession.php:243
‪TYPO3\CMS\Core\Session\UserSession\isPermanent
‪isPermanent()
Definition: UserSession.php:185
‪TYPO3\CMS\Core\Session\UserSession\$isNew
‪bool $isNew
Definition: UserSession.php:54
‪TYPO3\CMS\Core\Session\UserSession\$wasUpdated
‪bool $wasUpdated
Definition: UserSession.php:52
‪TYPO3\CMS\Core\Security\JwtTrait
Definition: JwtTrait.php:32
‪TYPO3\CMS\Core\Session\UserSession
Definition: UserSession.php:45
‪TYPO3\CMS\Core\Session\UserSession\createFromRecord
‪static createFromRecord(string $id, array $record, bool $markAsNew=false)
Definition: UserSession.php:223
‪TYPO3\CMS\Core\Session\UserSession\$isPermanent
‪bool $isPermanent
Definition: UserSession.php:55
‪TYPO3\CMS\Core\Session
‪TYPO3\CMS\Core\Session\UserSession\$identifier
‪string $identifier
Definition: UserSession.php:48
‪TYPO3\CMS\Core\Session\UserSession\isNew
‪isNew()
Definition: UserSession.php:177
‪TYPO3\CMS\Core\Session\UserSession\$userId
‪int $userId
Definition: UserSession.php:49
‪TYPO3\CMS\Core\Session\UserSession\getIpLock
‪string getIpLock()
Definition: UserSession.php:169
‪TYPO3\CMS\Core\Session\UserSession\__construct
‪__construct(string $identifier, int $userId, int $lastUpdated, array $data=[])
Definition: UserSession.php:57
‪TYPO3\CMS\Core\Session\UserSession\getData
‪array getData()
Definition: UserSession.php:130
‪TYPO3\CMS\Core\Session\UserSession\dataWasUpdated
‪dataWasUpdated()
Definition: UserSession.php:152
‪TYPO3\CMS\Core\Session\UserSession\resolveIdentifierFromJwt
‪static non empty string null resolveIdentifierFromJwt(string $cookieValue, CookieScope $scope)
Definition: UserSession.php:261
‪TYPO3\CMS\Webhooks\Message\$record
‪identifier readonly int readonly array $record
Definition: PageModificationMessage.php:36
‪TYPO3\CMS\Core\Security\JwtTrait\encodeHashSignedJwt
‪static encodeHashSignedJwt(array $payload, Key $key, SecretIdentifier $identifier=null)
Definition: JwtTrait.php:57
‪TYPO3\CMS\Core\Session\UserSession\$lastUpdated
‪int $lastUpdated
Definition: UserSession.php:50
‪TYPO3\CMS\Core\Session\UserSession\$ipLock
‪string $ipLock
Definition: UserSession.php:53
‪TYPO3\CMS\Core\Session\UserSession\overrideData
‪overrideData(array $data)
Definition: UserSession.php:139
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Log\LogManager
Definition: LogManager.php:33
‪TYPO3\CMS\Core\Session\UserSession\getJwt
‪string getJwt(?CookieScope $scope=null)
Definition: UserSession.php:205
‪TYPO3\CMS\Core\Session\UserSession\hasData
‪hasData()
Definition: UserSession.php:112
‪TYPO3\CMS\Core\Session\UserSession\getLastUpdated
‪int getLastUpdated()
Definition: UserSession.php:84
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Session\UserSession\getUserId
‪int getUserId()
Definition: UserSession.php:76
‪TYPO3\CMS\Core\Session\UserSession\needsUpdate
‪needsUpdate()
Definition: UserSession.php:193
‪TYPO3\CMS\Core\Session\UserSession\$data
‪array $data
Definition: UserSession.php:51