‪TYPO3CMS  ‪main
SetCookieService.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 
18 namespace ‪TYPO3\CMS\Core\Http;
19 
20 use Psr\Http\Message\ServerRequestInterface;
21 use Psr\Log\LoggerInterface;
22 use Symfony\Component\HttpFoundation\Cookie;
26 
33 {
36 
37  protected readonly LoggerInterface ‪$logger;
38 
39  public static function ‪create(string $name, string $type): self
40  {
41  $lifetime = (int)(‪$GLOBALS['TYPO3_CONF_VARS'][$type]['lifetime'] ?? 0);
42  return new self($name, $type, $lifetime);
43  }
44 
45  private function ‪__construct(
46  protected readonly string $name,
47  protected readonly string $loginType,
55  protected readonly int $lifetime
56  ) {
57  $this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
58  }
59 
63  public function ‪setSessionCookie(UserSession $userSession, NormalizedParams $normalizedParams): ?Cookie
64  {
65  $setCookie = null;
66  $isRefreshTimeBasedCookie = $this->‪isRefreshTimeBasedCookie($userSession);
67  if ($this->‪isSetSessionCookie($userSession) || $isRefreshTimeBasedCookie) {
68  // Get the domain to be used for the cookie (if any):
69  $cookieScope = $this->‪getCookieScope($normalizedParams);
70  // If the cookie lifetime is set, use it:
71  $cookieExpire = $isRefreshTimeBasedCookie ? ‪$GLOBALS['EXEC_TIME'] + $this->lifetime : 0;
72  // Valid options are "strict", "lax" or "none", whereas "none" only works in HTTPS requests (default & fallback is "strict")
73  $cookieSameSite = $this->‪sanitizeSameSiteCookieValue(
74  strtolower(‪$GLOBALS['TYPO3_CONF_VARS'][$this->loginType]['cookieSameSite'] ?? Cookie::SAMESITE_STRICT)
75  );
76  // Use the secure option when the current request is served by a secure connection:
77  // SameSite "none" needs the secure option (only allowed on HTTPS)
78  $isSecure = $cookieSameSite === Cookie::SAMESITE_NONE || $normalizedParams->isHttps();
79  $sessionId = $userSession->getIdentifier();
80  $cookieValue = $userSession->getJwt($cookieScope);
81  $setCookie = new Cookie(
82  $this->name,
83  $cookieValue,
84  $cookieExpire,
85  $cookieScope->path,
86  // Host-Only cookies need to be provided without an explicit domain,
87  // see https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.2.3
88  // and https://datatracker.ietf.org/doc/html/rfc6265#section-5.3
89  // | * If the value of the Domain attribute is "example.com", the user agent will include the cookie
90  // | in the Cookie header when making HTTP requests to example.com, www.example.com, and www.corp.example.com
91  // | * If the server omits the Domain attribute, the user agent will return the cookie only to the origin server.
92  $cookieScope->hostOnly ? null : $cookieScope->domain,
93  $isSecure,
94  true,
95  false,
96  $cookieSameSite
97  );
98  $message = $isRefreshTimeBasedCookie ? 'Updated Cookie: {session}, {domain}' : 'Set Cookie: {session}, {domain}';
99  $this->logger->debug($message, [
100  'session' => sha1($sessionId),
101  'domain' => $cookieScope->domain,
102  ]);
103  }
104  return $setCookie;
105  }
106 
110  public function ‪isSetSessionCookie(UserSession $userSession, bool $forceSetCookie = false): bool
111  {
112  if ($this->loginType === 'FE') {
113  return ($userSession->isNew() || $forceSetCookie)
114  && ($this->lifetime === 0 || !$userSession->isPermanent());
115  }
116  return $userSession->isNew() && $this->lifetime === 0;
117  }
118 
124  public function ‪isRefreshTimeBasedCookie(UserSession $userSession): bool
125  {
126  if ($this->loginType === 'FE') {
127  return $this->lifetime > 0 && $userSession->isPermanent();
128  }
129  return $this->lifetime > 0;
130  }
131 
138  public function ‪isCookieSet(?ServerRequestInterface $request, ?UserSession $userSession): bool
139  {
140  $isRefreshTimeBasedCookie = $userSession && $this->‪isRefreshTimeBasedCookie($userSession);
141  if ($isRefreshTimeBasedCookie || $this->‪isSetSessionCookie($userSession)) {
142  return true;
143  }
144  if ($request && isset($request->getCookieParams()[$this->name])) {
145  return true;
146  }
147  return false;
148  }
149 
153  public function ‪removeCookie(NormalizedParams $normalizedParams): Cookie
154  {
155  $scope = $this->‪getCookieScope($normalizedParams);
156  return new Cookie(
157  $this->name,
158  '',
159  -1,
160  $scope->path,
161  $scope->domain
162  );
163  }
164 }
‪TYPO3\CMS\Core\Session\UserSession\getIdentifier
‪string getIdentifier()
Definition: UserSession.php:68
‪TYPO3\CMS\Core\Session\UserSession\isPermanent
‪isPermanent()
Definition: UserSession.php:185
‪TYPO3\CMS\Core\Session\UserSession
Definition: UserSession.php:45
‪TYPO3\CMS\Core\Session\UserSession\isNew
‪isNew()
Definition: UserSession.php:177
‪TYPO3\CMS\Core\Http\NormalizedParams\isHttps
‪bool isHttps()
Definition: NormalizedParams.php:340
‪$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\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Http\NormalizedParams
Definition: NormalizedParams.php:38
‪TYPO3\CMS\Core\Http
Definition: AbstractApplication.php:18