‪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 
169  public static function ‪getCookieName()
170  {
171  $configuredCookieName = trim(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['cookieName']);
172  if (empty($configuredCookieName)) {
173  $configuredCookieName = 'fe_typo_user';
174  }
175  return $configuredCookieName;
176  }
177 
184  protected function ‪isSetSessionCookie()
185  {
186  return ‪SetCookieService::create($this->name, $this->loginType)->isSetSessionCookie($this->userSession, $this->forceSetCookie);
187  }
188 
195  protected function ‪isRefreshTimeBasedCookie()
196  {
197  return ‪SetCookieService::create($this->name, $this->loginType)->isRefreshTimeBasedCookie($this->userSession);
198  }
199 
206  public function ‪getLoginFormData(ServerRequestInterface $request)
207  {
208  ‪$loginData = parent::getLoginFormData($request);
209  // Needed in order to fetch users which are already logged-in due to fetching from session
210  if (LoginType::tryFrom(‪$loginData['status'] ?? '') !== LoginType::LOGIN) {
211  $this->checkPid_value = null;
212  }
213 
214  if (‪$GLOBALS['TYPO3_CONF_VARS']['FE']['permalogin'] == 0 || ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['permalogin'] == 1) {
215  $isPermanent = $request->getParsedBody()[‪$this->formfield_permanent] ?? '';
216  if (strlen((string)$isPermanent) != 1) {
217  $isPermanent = ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['permalogin'];
218  } elseif (!$isPermanent) {
219  // To make sure the user gets a session cookie and doesn't keep a possibly existing time based cookie,
220  // we need to force setting the session cookie here
221  $this->forceSetCookie = true;
222  }
223  $isPermanent = (bool)$isPermanent;
224  } elseif (‪$GLOBALS['TYPO3_CONF_VARS']['FE']['permalogin'] == 2) {
225  $isPermanent = true;
226  } else {
227  $isPermanent = false;
228  }
229  ‪$loginData['permanent'] = $isPermanent;
230  $this->is_permanent = $isPermanent;
231  return ‪$loginData;
232  }
233 
242  public function ‪createUserSession(array $tempuser): UserSession
243  {
244  // At this point we do not know if we need to set a session or a permanent cookie
245  // So we force the cookie to be set after authentication took place, which will
246  // then call setSessionCookie(), which will set a cookie with correct settings.
247  $this->dontSetCookie = false;
248  $tempUserId = (int)($tempuser[$this->userid_column] ?? 0);
249  $session = $this->userSessionManager->elevateToFixatedUserSession(
250  $this->userSession,
251  $tempUserId,
253  );
254  // Updating lastLogin_column carrying information about last login.
255  $this->‪updateLoginTimestamp($tempUserId);
256  return $session;
257  }
258 
264  public function ‪fetchGroupData(ServerRequestInterface $request)
265  {
266  $this->userGroups = [];
267  $this->groupData = [
268  'title' => [],
269  'uid' => [],
270  'pid' => [],
271  ];
272 
273  $groupDataArr = [];
274  if (is_array($this->user)) {
275  $this->logger->debug('Get usergroups for user', [
276  $this->userid_column => $this->user[$this->userid_column],
277  $this->username_column => $this->user[$this->username_column],
278  ]);
279  $groupDataArr = GeneralUtility::makeInstance(GroupResolver::class)->resolveGroupsForUser($this->user, $this->usergroup_table);
280  }
281  // Fire an event for any kind of user (even when no specific user is here, using hideLogin feature)
282  $dispatcher = GeneralUtility::makeInstance(EventDispatcherInterface::class);
283  $event = $dispatcher->dispatch(new ModifyResolvedFrontendGroupsEvent($this, $groupDataArr, $request));
284  $groupDataArr = $event->getGroups();
285 
286  if (empty($groupDataArr)) {
287  $this->logger->debug('No usergroups found');
288  } else {
289  $this->logger->debug('{count} usergroup records found', ['count' => count($groupDataArr)]);
290  }
291  foreach ($groupDataArr as ‪$groupData) {
292  $groupId = (int)‪$groupData['uid'];
293  $this->groupData['title'][$groupId] = ‪$groupData['title'] ?? '';
294  $this->groupData['uid'][$groupId] = ‪$groupData['uid'] ?? 0;
295  $this->groupData['pid'][$groupId] = ‪$groupData['pid'] ?? 0;
296  $this->userGroups[$groupId] = ‪$groupData;
297  }
298  // Sort information
299  ksort($this->groupData['title']);
300  ksort($this->groupData['uid']);
301  ksort($this->groupData['pid']);
302  }
303 
310  public function ‪createUserAspect(bool $respectUserGroups = true): UserAspect
311  {
312  ‪$userGroups = [0];
313  $isUserAndGroupSet = is_array($this->user) && !empty($this->userGroups);
314  if ($isUserAndGroupSet) {
315  // group -2 is not an existing group, but denotes a 'default' group when a user IS logged in.
316  // This is used to let elements be shown for all logged in users!
317  ‪$userGroups[] = -2;
318  $groupsFromUserRecord = array_keys($this->userGroups);
319  } else {
320  // group -1 is not an existing group, but denotes a 'default' group when not logged in.
321  // This is used to let elements be hidden, when a user is logged in!
322  ‪$userGroups[] = -1;
323  if ($respectUserGroups) {
324  // 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.
325  $groupsFromUserRecord = array_keys($this->userGroups);
326  } else {
327  // Set to blank since we will NOT risk any groups being set when no logins are allowed!
328  $groupsFromUserRecord = [];
329  }
330  }
331  // Make unique and sort the groups
332  $groupsFromUserRecord = array_unique($groupsFromUserRecord);
333  if ($respectUserGroups && !empty($groupsFromUserRecord)) {
334  sort($groupsFromUserRecord);
335  ‪$userGroups = array_merge(‪$userGroups, $groupsFromUserRecord);
336  }
337 
338  // For every 60 seconds the is_online timestamp for a logged-in user is updated
339  if ($isUserAndGroupSet) {
340  $this->‪updateOnlineTimestamp();
341  }
342 
343  $this->logger->debug('Valid frontend usergroups: {groups}', ['groups' => implode(',', ‪$userGroups)]);
344  return GeneralUtility::makeInstance(UserAspect::class, $this, ‪$userGroups);
345  }
346 
347  /*****************************************
348  *
349  * Session data management functions
350  *
351  ****************************************/
359  public function ‪storeSessionData()
360  {
361  // Saves UC and SesData if changed.
362  if ($this->userData_change) {
363  $this->‪writeUC();
364  }
365 
366  if ($this->userSession->dataWasUpdated()) {
367  if (!$this->userSession->hasData()) {
368  // Remove session-data
369  $this->‪removeSessionData();
370  // Remove cookie if not logged in as the session data is removed as well
371  if (empty($this->user['uid']) && $this->‪isCookieSet()) {
372  $this->‪removeCookie();
373  }
374  } elseif (!$this->userSessionManager->isSessionPersisted($this->userSession)) {
375  // Create a new session entry in the backend
376  $this->userSession = $this->userSessionManager->fixateAnonymousSession($this->userSession, (bool)$this->is_permanent);
377  // Now set the cookie (= fix the session)
378  $this->‪setSessionCookie();
379  } else {
380  // Update session data of an already fixated session
381  $this->userSession = $this->userSessionManager->updateSession($this->userSession);
382  }
383  }
384  }
385 
389  public function ‪removeSessionData()
390  {
391  $this->userSession->overrideData([]);
392  if ($this->userSessionManager->isSessionPersisted($this->userSession)) {
393  // Remove session record if $this->user is empty or in case the session is anonymous
394  if (empty($this->user) || $this->userSession->isAnonymous()) {
395  $this->userSessionManager->removeSession($this->userSession);
396  } else {
397  $this->userSession = $this->userSessionManager->updateSession($this->userSession);
398  }
399  }
400  }
401 
408  protected function ‪regenerateSessionId()
409  {
410  parent::regenerateSessionId();
411  // We force the cookie to be set later in the authentication process
412  $this->dontSetCookie = false;
413  }
414 
424  public function ‪getKey($type, $key)
425  {
426  if (!$key) {
427  return null;
428  }
429  $value = null;
430  switch ($type) {
431  case 'user':
432  $value = $this->uc[$key] ?? null;
433  break;
434  case 'ses':
435  $value = $this->‪getSessionData($key);
436  break;
437  }
438  return $value;
439  }
440 
452  public function ‪setKey($type, $key, $data)
453  {
454  if (!$key) {
455  return;
456  }
457  switch ($type) {
458  case 'user':
459  if ($this->user['uid'] ?? 0) {
460  if ($data === null) {
461  unset($this->uc[$key]);
462  } else {
463  $this->uc[$key] = $data;
464  }
465  $this->userData_change = true;
466  }
467  break;
468  case 'ses':
469  $this->‪setSessionData($key, $data);
470  break;
471  }
472  }
473 
480  public function ‪setAndSaveSessionData($key, $data)
481  {
482  $this->‪setSessionData($key, $data);
483  $this->‪storeSessionData();
484  }
485 
491  public function ‪updateOnlineTimestamp()
492  {
493  if (!is_array($this->user)
494  || !($this->user['uid'] ?? 0)
495  || $this->user['uid'] === PHP_INT_MAX // Simulated preview user (flagged with PHP_INT_MAX uid)
496  || ($this->user['is_online'] ?? 0) >= ‪$GLOBALS['EXEC_TIME'] - 60) {
497  return;
498  }
499  $dbConnection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->user_table);
500  $dbConnection->update(
501  $this->user_table,
502  ['is_online' => ‪$GLOBALS['EXEC_TIME']],
503  ['uid' => (int)$this->user['uid']]
504  );
505  $this->user['is_online'] = ‪$GLOBALS['EXEC_TIME'];
506  }
507 }
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\getLoginFormData
‪array getLoginFormData(ServerRequestInterface $request)
Definition: FrontendUserAuthentication.php:188
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$enablecolumns
‪array $enablecolumns
Definition: FrontendUserAuthentication.php:102
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\updateOnlineTimestamp
‪updateOnlineTimestamp()
Definition: FrontendUserAuthentication.php:473
‪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:742
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$lastLogin_column
‪string $lastLogin_column
Definition: FrontendUserAuthentication.php:89
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\removeSessionData
‪removeSessionData()
Definition: FrontendUserAuthentication.php:371
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\$userGroups
‪array $userGroups
Definition: AbstractUserAuthentication.php:173
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\storeSessionData
‪storeSessionData()
Definition: FrontendUserAuthentication.php:341
‪TYPO3\CMS\Core\Session\UserSession
Definition: UserSession.php:45
‪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\Frontend\Authentication\FrontendUserAuthentication\setAndSaveSessionData
‪setAndSaveSessionData($key, $data)
Definition: FrontendUserAuthentication.php:462
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$formfield_uname
‪string $formfield_uname
Definition: FrontendUserAuthentication.php:43
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\getCookieName
‪static string getCookieName()
Definition: FrontendUserAuthentication.php:151
‪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\fetchGroupData
‪fetchGroupData(ServerRequestInterface $request)
Definition: FrontendUserAuthentication.php:246
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\setSessionData
‪setSessionData($key, $data)
Definition: AbstractUserAuthentication.php:1013
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\isRefreshTimeBasedCookie
‪bool isRefreshTimeBasedCookie()
Definition: FrontendUserAuthentication.php:177
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\regenerateSessionId
‪regenerateSessionId()
Definition: FrontendUserAuthentication.php:390
‪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:1001
‪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:224
‪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:166
‪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:434
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\removeCookie
‪removeCookie($cookieName=null)
Definition: AbstractUserAuthentication.php:843
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\isCookieSet
‪bool isCookieSet()
Definition: AbstractUserAuthentication.php:855
‪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:302
‪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:292
‪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:406
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication
Definition: AbstractUserAuthentication.php:64
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\$username_column
‪string $username_column
Definition: FrontendUserAuthentication.php:73
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\writeUC
‪writeUC()
Definition: AbstractUserAuthentication.php:921