‪TYPO3CMS  ‪main
FrontendUserAuthentication.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
18 use Psr\EventDispatcher\EventDispatcherInterface;
19 use Psr\Http\Message\ServerRequestInterface;
28 
33 {
38  public ‪$loginType = 'FE';
39 
45  protected ‪$formfield_uname = 'user';
46 
52  protected ‪$formfield_uident = 'pass';
53 
59  protected ‪$formfield_status = 'logintype';
60 
68  protected ‪$formfield_permanent = 'permalogin';
69 
74  public ‪$user_table = 'fe_users';
75 
80  public ‪$username_column = 'username';
81 
86  public ‪$userident_column = 'password';
87 
92  public ‪$userid_column = 'uid';
93 
99  protected ‪$lastLogin_column = 'lastlogin';
100 
104  public ‪$usergroup_column = 'usergroup';
105 
109  public ‪$usergroup_table = 'fe_groups';
110 
115  public ‪$enablecolumns = [
116  'deleted' => 'deleted',
117  'disabled' => 'disable',
118  'starttime' => 'starttime',
119  'endtime' => 'endtime',
120  ];
121 
125  public ‪$groupData = [
126  'title' => [],
127  'uid' => [],
128  'pid' => [],
129  ];
130 
134  protected ‪$userData_change = false;
135 
140  protected ‪$is_permanent = false;
141 
146  protected ‪$forceSetCookie = false;
147 
155  protected ‪$dontSetCookie = true;
156 
157  public function ‪__construct()
158  {
159  $this->name = ‪self::getCookieName();
160  parent::__construct();
161  $this->checkPid = (bool)(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['checkFeUserPid'] ?? true);
162  }
163 
167  public static function ‪getCookieName(): string
168  {
169  $configuredCookieName = trim((string)(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['cookieName'] ?? ''));
170  return $configuredCookieName !== '' ? $configuredCookieName : 'fe_typo_user';
171  }
172 
179  protected function ‪isSetSessionCookie()
180  {
181  return ‪SetCookieService::create($this->name, $this->loginType)->isSetSessionCookie($this->userSession, $this->forceSetCookie);
182  }
183 
190  protected function ‪isRefreshTimeBasedCookie()
191  {
192  return ‪SetCookieService::create($this->name, $this->loginType)->isRefreshTimeBasedCookie($this->userSession);
193  }
194 
201  public function ‪getLoginFormData(ServerRequestInterface $request)
202  {
203  ‪$loginData = parent::getLoginFormData($request);
204  // Needed in order to fetch users which are already logged-in due to fetching from session
205  if (LoginType::tryFrom(‪$loginData['status'] ?? '') !== LoginType::LOGIN) {
206  $this->checkPid_value = null;
207  }
208 
209  if (‪$GLOBALS['TYPO3_CONF_VARS']['FE']['permalogin'] == 0 || ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['permalogin'] == 1) {
210  $isPermanent = $request->getParsedBody()[‪$this->formfield_permanent] ?? '';
211  if (strlen((string)$isPermanent) != 1) {
212  $isPermanent = ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['permalogin'];
213  } elseif (!$isPermanent) {
214  // To make sure the user gets a session cookie and doesn't keep a possibly existing time based cookie,
215  // we need to force setting the session cookie here
216  $this->forceSetCookie = true;
217  }
218  $isPermanent = (bool)$isPermanent;
219  } elseif (‪$GLOBALS['TYPO3_CONF_VARS']['FE']['permalogin'] == 2) {
220  $isPermanent = true;
221  } else {
222  $isPermanent = false;
223  }
224  ‪$loginData['permanent'] = $isPermanent;
225  $this->is_permanent = $isPermanent;
226  return ‪$loginData;
227  }
228 
237  public function ‪createUserSession(array $tempuser): UserSession
238  {
239  // At this point we do not know if we need to set a session or a permanent cookie
240  // So we force the cookie to be set after authentication took place, which will
241  // then call setSessionCookie(), which will set a cookie with correct settings.
242  $this->dontSetCookie = false;
243  $tempUserId = (int)($tempuser[$this->userid_column] ?? 0);
244  $session = $this->userSessionManager->elevateToFixatedUserSession(
245  $this->userSession,
246  $tempUserId,
248  );
249  // Updating lastLogin_column carrying information about last login.
250  $this->‪updateLoginTimestamp($tempUserId);
251  return $session;
252  }
253 
259  public function ‪fetchGroupData(ServerRequestInterface $request)
260  {
261  $this->userGroups = [];
262  $this->groupData = [
263  'title' => [],
264  'uid' => [],
265  'pid' => [],
266  ];
267 
268  $groupDataArr = [];
269  if (is_array($this->user)) {
270  $this->logger->debug('Get usergroups for user', [
271  $this->userid_column => $this->‪getUserId(),
272  $this->username_column => $this->‪getUserName(),
273  ]);
274  $groupDataArr = GeneralUtility::makeInstance(GroupResolver::class)->resolveGroupsForUser($this->user, $this->usergroup_table);
275  }
276  // Fire an event for any kind of user (even when no specific user is here, using hideLogin feature)
277  $dispatcher = GeneralUtility::makeInstance(EventDispatcherInterface::class);
278  $event = $dispatcher->dispatch(new ModifyResolvedFrontendGroupsEvent($this, $groupDataArr, $request));
279  $groupDataArr = $event->getGroups();
280 
281  if (empty($groupDataArr)) {
282  $this->logger->debug('No usergroups found');
283  } else {
284  $this->logger->debug('{count} usergroup records found', ['count' => count($groupDataArr)]);
285  }
286  foreach ($groupDataArr as ‪$groupData) {
287  $groupId = (int)‪$groupData['uid'];
288  $this->groupData['title'][$groupId] = ‪$groupData['title'] ?? '';
289  $this->groupData['uid'][$groupId] = ‪$groupData['uid'] ?? 0;
290  $this->groupData['pid'][$groupId] = ‪$groupData['pid'] ?? 0;
291  $this->userGroups[$groupId] = ‪$groupData;
292  }
293  // Sort information
294  ksort($this->groupData['title']);
295  ksort($this->groupData['uid']);
296  ksort($this->groupData['pid']);
297  }
298 
305  public function ‪createUserAspect(bool $respectUserGroups = true): UserAspect
306  {
307  ‪$userGroups = [0];
308  $isUserAndGroupSet = is_array($this->user) && !empty($this->userGroups);
309  if ($isUserAndGroupSet) {
310  // group -2 is not an existing group, but denotes a 'default' group when a user IS logged in.
311  // This is used to let elements be shown for all logged in users!
312  ‪$userGroups[] = -2;
313  $groupsFromUserRecord = array_keys($this->userGroups);
314  } else {
315  // group -1 is not an existing group, but denotes a 'default' group when not logged in.
316  // This is used to let elements be hidden, when a user is logged in!
317  ‪$userGroups[] = -1;
318  if ($respectUserGroups) {
319  // For cases where logins are not banned from a branch usergroups can be set based on IP masks so we should add the usergroups uids.
320  $groupsFromUserRecord = array_keys($this->userGroups);
321  } else {
322  // Set to blank since we will NOT risk any groups being set when no logins are allowed!
323  $groupsFromUserRecord = [];
324  }
325  }
326  // Make unique and sort the groups
327  $groupsFromUserRecord = array_unique($groupsFromUserRecord);
328  if ($respectUserGroups && !empty($groupsFromUserRecord)) {
329  sort($groupsFromUserRecord);
330  ‪$userGroups = array_merge(‪$userGroups, $groupsFromUserRecord);
331  }
332 
333  // For every 60 seconds the is_online timestamp for a logged-in user is updated
334  if ($isUserAndGroupSet) {
335  $this->‪updateOnlineTimestamp();
336  }
337 
338  $this->logger->debug('Valid frontend usergroups: {groups}', ['groups' => implode(',', ‪$userGroups)]);
339  return GeneralUtility::makeInstance(UserAspect::class, $this, ‪$userGroups);
340  }
341 
342  /*****************************************
343  *
344  * Session data management functions
345  *
346  ****************************************/
354  public function ‪storeSessionData()
355  {
356  // Saves UC and SesData if changed.
357  if ($this->userData_change) {
358  $this->‪writeUC();
359  }
360 
361  if ($this->userSession->dataWasUpdated()) {
362  if (!$this->userSession->hasData()) {
363  // Remove session-data
364  $this->‪removeSessionData();
365  // Remove cookie if not logged in as the session data is removed as well
366  if (empty($this->user['uid']) && $this->‪isCookieSet()) {
367  $this->‪removeCookie();
368  }
369  } elseif (!$this->userSessionManager->isSessionPersisted($this->userSession)) {
370  // Create a new session entry in the backend
371  $this->userSession = $this->userSessionManager->fixateAnonymousSession($this->userSession, (bool)$this->is_permanent);
372  // Now set the cookie (= fix the session)
373  $this->‪setSessionCookie();
374  } else {
375  // Update session data of an already fixated session
376  $this->userSession = $this->userSessionManager->updateSession($this->userSession);
377  }
378  }
379  }
380 
384  public function ‪removeSessionData()
385  {
386  $this->userSession->overrideData([]);
387  if ($this->userSessionManager->isSessionPersisted($this->userSession)) {
388  // Remove session record if $this->user is empty or in case the session is anonymous
389  if (empty($this->user) || $this->userSession->isAnonymous()) {
390  $this->userSessionManager->removeSession($this->userSession);
391  } else {
392  $this->userSession = $this->userSessionManager->updateSession($this->userSession);
393  }
394  }
395  }
396 
403  protected function ‪regenerateSessionId()
404  {
405  parent::regenerateSessionId();
406  // We force the cookie to be set later in the authentication process
407  $this->dontSetCookie = false;
408  }
409 
419  public function ‪getKey($type, $key)
420  {
421  if (!$key) {
422  return null;
423  }
424  $value = null;
425  switch ($type) {
426  case 'user':
427  $value = $this->uc[$key] ?? null;
428  break;
429  case 'ses':
430  $value = $this->‪getSessionData($key);
431  break;
432  }
433  return $value;
434  }
435 
447  public function ‪setKey($type, $key, $data)
448  {
449  if (!$key) {
450  return;
451  }
452  switch ($type) {
453  case 'user':
454  if ($this->user['uid'] ?? 0) {
455  if ($data === null) {
456  unset($this->uc[$key]);
457  } else {
458  $this->uc[$key] = $data;
459  }
460  $this->userData_change = true;
461  }
462  break;
463  case 'ses':
464  $this->‪setSessionData($key, $data);
465  break;
466  }
467  }
468 
475  public function ‪setAndSaveSessionData($key, $data)
476  {
477  $this->‪setSessionData($key, $data);
478  $this->‪storeSessionData();
479  }
480 
486  public function ‪updateOnlineTimestamp()
487  {
488  if (!is_array($this->user)
489  || !($this->user['uid'] ?? 0)
490  || $this->user['uid'] === PHP_INT_MAX // Simulated preview user (flagged with PHP_INT_MAX uid)
491  || ($this->user['is_online'] ?? 0) >= ‪$GLOBALS['EXEC_TIME'] - 60) {
492  return;
493  }
494  $dbConnection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->user_table);
495  $dbConnection->update(
496  $this->user_table,
497  ['is_online' => ‪$GLOBALS['EXEC_TIME']],
498  ['uid' => (int)$this->user['uid']]
499  );
500  $this->user['is_online'] = ‪$GLOBALS['EXEC_TIME'];
501  }
502 }
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\getLoginFormData
‪array getLoginFormData(ServerRequestInterface $request)
Definition: FrontendUserAuthentication.php:183
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$enablecolumns
‪array $enablecolumns
Definition: FrontendUserAuthentication.php:102
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\updateOnlineTimestamp
‪updateOnlineTimestamp()
Definition: FrontendUserAuthentication.php:468
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$user_table
‪string $user_table
Definition: FrontendUserAuthentication.php:68
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\updateLoginTimestamp
‪updateLoginTimestamp(int $userId)
Definition: AbstractUserAuthentication.php:743
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$lastLogin_column
‪string $lastLogin_column
Definition: FrontendUserAuthentication.php:89
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\removeSessionData
‪removeSessionData()
Definition: FrontendUserAuthentication.php:366
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\$userGroups
‪array $userGroups
Definition: AbstractUserAuthentication.php:174
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\storeSessionData
‪storeSessionData()
Definition: FrontendUserAuthentication.php:336
‪TYPO3\CMS\Core\Session\UserSession
Definition: UserSession.php:45
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\getUserName
‪getUserName()
Definition: AbstractUserAuthentication.php:1245
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\__construct
‪__construct()
Definition: FrontendUserAuthentication.php:139
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$userident_column
‪string $userident_column
Definition: FrontendUserAuthentication.php:78
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\getUserId
‪getUserId()
Definition: AbstractUserAuthentication.php:1237
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\setAndSaveSessionData
‪setAndSaveSessionData($key, $data)
Definition: FrontendUserAuthentication.php:457
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$formfield_uname
‪string $formfield_uname
Definition: FrontendUserAuthentication.php:43
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$formfield_status
‪string $formfield_status
Definition: FrontendUserAuthentication.php:55
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$loginType
‪string $loginType
Definition: FrontendUserAuthentication.php:37
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\getCookieName
‪static getCookieName()
Definition: FrontendUserAuthentication.php:149
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\fetchGroupData
‪fetchGroupData(ServerRequestInterface $request)
Definition: FrontendUserAuthentication.php:241
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\setSessionData
‪setSessionData($key, $data)
Definition: AbstractUserAuthentication.php:1017
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\isRefreshTimeBasedCookie
‪bool isRefreshTimeBasedCookie()
Definition: FrontendUserAuthentication.php:172
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\regenerateSessionId
‪regenerateSessionId()
Definition: FrontendUserAuthentication.php:385
‪TYPO3\CMS\Webhooks\Message\$loginData
‪identifier readonly UriInterface readonly array $loginData
Definition: LoginErrorOccurredMessage.php:37
‪TYPO3\CMS\Core\Authentication\LoginType
‪LoginType
Definition: LoginType.php:24
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$is_permanent
‪bool $is_permanent
Definition: FrontendUserAuthentication.php:124
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$usergroup_table
‪string $usergroup_table
Definition: FrontendUserAuthentication.php:97
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\getSessionData
‪mixed getSessionData($key)
Definition: AbstractUserAuthentication.php:1005
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$usergroup_column
‪string $usergroup_column
Definition: FrontendUserAuthentication.php:93
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\createUserSession
‪UserSession createUserSession(array $tempuser)
Definition: FrontendUserAuthentication.php:219
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$forceSetCookie
‪bool $forceSetCookie
Definition: FrontendUserAuthentication.php:129
‪TYPO3\CMS\Core\Authentication\GroupResolver
Definition: GroupResolver.php:36
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$formfield_uident
‪string $formfield_uident
Definition: FrontendUserAuthentication.php:49
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$userid_column
‪string $userid_column
Definition: FrontendUserAuthentication.php:83
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\isSetSessionCookie
‪bool isSetSessionCookie()
Definition: FrontendUserAuthentication.php:161
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$dontSetCookie
‪bool $dontSetCookie
Definition: FrontendUserAuthentication.php:137
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$userData_change
‪bool $userData_change
Definition: FrontendUserAuthentication.php:119
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\setKey
‪setKey($type, $key, $data)
Definition: FrontendUserAuthentication.php:429
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\removeCookie
‪removeCookie($cookieName=null)
Definition: AbstractUserAuthentication.php:844
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\isCookieSet
‪bool isCookieSet()
Definition: AbstractUserAuthentication.php:856
‪TYPO3\CMS\Frontend\Authentication
Definition: FrontendUserAuthentication.php:16
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication
Definition: FrontendUserAuthentication.php:33
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\setSessionCookie
‪setSessionCookie()
Definition: AbstractUserAuthentication.php:303
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Frontend\Authentication\ModifyResolvedFrontendGroupsEvent
Definition: ModifyResolvedFrontendGroupsEvent.php:27
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$groupData
‪array $groupData
Definition: FrontendUserAuthentication.php:111
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\createUserAspect
‪createUserAspect(bool $respectUserGroups=true)
Definition: FrontendUserAuthentication.php:287
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$formfield_permanent
‪string $formfield_permanent
Definition: FrontendUserAuthentication.php:63
‪TYPO3\CMS\Core\Context\UserAspect
Definition: UserAspect.php:37
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\getKey
‪mixed getKey($type, $key)
Definition: FrontendUserAuthentication.php:401
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication
Definition: AbstractUserAuthentication.php:65
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$username_column
‪string $username_column
Definition: FrontendUserAuthentication.php:73
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\writeUC
‪writeUC()
Definition: AbstractUserAuthentication.php:922