diff --git a/core/core.services.yml b/core/core.services.yml
index 831eb541ad..b1e587a3a3 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -1721,6 +1721,6 @@ services:
       - { name: backend_overridable }
   tempstore.shared:
     class: Drupal\Core\TempStore\SharedTempStoreFactory
-    arguments: ['@keyvalue.expirable', '@lock', '@request_stack', '%tempstore.expire%']
+    arguments: ['@keyvalue.expirable', '@lock', '@request_stack', '@current_user', '@session', '%tempstore.expire%']
     tags:
       - { name: backend_overridable }
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index c75da59c7a..d0031e3535 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -1547,6 +1547,8 @@ function install_bootstrap_full() {
   $session = \Drupal::service('session');
   \Drupal::request()->setSession($session);
   $session->start();
+  // Ensure the session is maintained throughout the install.
+  $session->set('_drupal_installing', TRUE);
 }
 
 /**
@@ -1844,6 +1846,9 @@ function install_finished(&$install_state) {
   // Installation profiles are always loaded last.
   module_set_weight($profile, 1000);
 
+  // Clean up the session flag.
+  \Drupal::service('session')->remove('_drupal_installing');
+
   // Build the router once after installing all modules.
   // This would normally happen upon KernelEvents::TERMINATE, but since the
   // installer does not use an HttpKernel, that event is never triggered.
diff --git a/core/lib/Drupal/Core/Session/MetadataBag.php b/core/lib/Drupal/Core/Session/MetadataBag.php
index ee0fbd4855..dad5dabdf1 100644
--- a/core/lib/Drupal/Core/Session/MetadataBag.php
+++ b/core/lib/Drupal/Core/Session/MetadataBag.php
@@ -51,7 +51,8 @@ class MetadataBag extends SymfonyMetadataBag {
   /**
    * Clear the CSRF token seed.
    */
-  public function clearCsrfTokenSeed() {
+  public function stampNew($lifetime = NULL) {
+    parent::stampNew($lifetime);
     unset($this->meta[static::CSRF_TOKEN_SEED]);
   }
 
diff --git a/core/lib/Drupal/Core/Session/SessionManager.php b/core/lib/Drupal/Core/Session/SessionManager.php
index 7981398678..0fcb915f25 100644
--- a/core/lib/Drupal/Core/Session/SessionManager.php
+++ b/core/lib/Drupal/Core/Session/SessionManager.php
@@ -2,7 +2,6 @@
 
 namespace Drupal\Core\Session;
 
-use Drupal\Component\Utility\Crypt;
 use Drupal\Core\Database\Connection;
 use Drupal\Core\DependencyInjection\DependencySerializationTrait;
 use Symfony\Component\HttpFoundation\RequestStack;
@@ -119,17 +118,6 @@ class SessionManager extends NativeSessionStorage implements SessionManagerInter
     }
 
     if (empty($result)) {
-      // Randomly generate a session identifier for this request. This is
-      // necessary because \Drupal\Core\TempStore\SharedTempStoreFactory::get()
-      // wants to know the future session ID of a lazily started session in
-      // advance.
-      //
-      // @todo: With current versions of PHP there is little reason to generate
-      //   the session id from within application code. Consider using the
-      //   default php session id instead of generating a custom one:
-      //   https://www.drupal.org/node/2238561
-      $this->setId(Crypt::randomBytesBase64());
-
       // Initialize the session global and attach the Symfony session bags.
       $_SESSION = [];
       $this->loadSession();
@@ -210,32 +198,7 @@ class SessionManager extends NativeSessionStorage implements SessionManagerInter
       return;
     }
 
-    // We do not support the optional $destroy and $lifetime parameters as long
-    // as #2238561 remains open.
-    if ($destroy || isset($lifetime)) {
-      throw new \InvalidArgumentException('The optional parameters $destroy and $lifetime of SessionManager::regenerate() are not supported currently');
-    }
-
-    if ($this->isStarted()) {
-      $old_session_id = $this->getId();
-      // Save and close the old session. Call the parent method to avoid issue
-      // with session destruction due to the session being considered obsolete.
-      parent::save();
-      // Ensure the session is reloaded correctly.
-      $this->startedLazy = TRUE;
-    }
-    session_id(Crypt::randomBytesBase64());
-
-    $this->getMetadataBag()->clearCsrfTokenSeed();
-
-    if (isset($old_session_id)) {
-      $params = session_get_cookie_params();
-      $expire = $params['lifetime'] ? REQUEST_TIME + $params['lifetime'] : 0;
-      setcookie($this->getName(), $this->getId(), $expire, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
-      $this->migrateStoredSession($old_session_id);
-    }
-
-    $this->startNow();
+    return parent::regenerate($destroy, $lifetime);
   }
 
   /**
@@ -326,18 +289,4 @@ class SessionManager extends NativeSessionStorage implements SessionManagerInter
     return array_intersect_key($mask, $_SESSION);
   }
 
-  /**
-   * Migrates the current session to a new session id.
-   *
-   * @param string $old_session_id
-   *   The old session ID. The new session ID is $this->getId().
-   */
-  protected function migrateStoredSession($old_session_id) {
-    $fields = ['sid' => Crypt::hashBase64($this->getId())];
-    $this->connection->update('sessions')
-      ->fields($fields)
-      ->condition('sid', Crypt::hashBase64($old_session_id))
-      ->execute();
-  }
-
 }
diff --git a/core/lib/Drupal/Core/TempStore/PrivateTempStore.php b/core/lib/Drupal/Core/TempStore/PrivateTempStore.php
index 4c89ff4170..6696671534 100644
--- a/core/lib/Drupal/Core/TempStore/PrivateTempStore.php
+++ b/core/lib/Drupal/Core/TempStore/PrivateTempStore.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Core\TempStore;
 
+use Drupal\Component\Utility\Crypt;
 use Drupal\Core\DependencyInjection\DependencySerializationTrait;
 use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface;
 use Drupal\Core\Lock\LockBackendInterface;
@@ -119,17 +120,16 @@ class PrivateTempStore {
    *   Thrown when a lock for the backend storage could not be acquired.
    */
   public function set($key, $value) {
-    // Ensure that an anonymous user has a session created for them, as
-    // otherwise subsequent page loads will not be able to retrieve their
-    // tempstore data.
     if ($this->currentUser->isAnonymous()) {
-      // @todo when https://www.drupal.org/node/2865991 is resolved, use force
-      //   start session API rather than setting an arbitrary value directly.
+      // Ensure that an anonymous user has a session created for them, as
+      // otherwise subsequent page loads will not be able to retrieve their
+      // tempstore data. Note this has to be done before the key is created as
+      // the owner is used in key creation.
       $this->startSession();
-      $this->requestStack
-        ->getCurrentRequest()
-        ->getSession()
-        ->set('core.tempstore.private', TRUE);
+      $session = $this->requestStack->getCurrentRequest()->getSession();
+      if (!$session->has('core.tempstore.private.owner')) {
+        $session->set('core.tempstore.private.owner', Crypt::randomBytesBase64());
+      }
     }
 
     $key = $this->createkey($key);
@@ -224,8 +224,10 @@ class PrivateTempStore {
   protected function getOwner() {
     $owner = $this->currentUser->id();
     if ($this->currentUser->isAnonymous()) {
+      // Check to see if an owner key exists in the session.
       $this->startSession();
-      $owner = $this->requestStack->getCurrentRequest()->getSession()->getId();
+      $session = $this->requestStack->getCurrentRequest()->getSession();
+      $owner = $session->get('core.tempstore.private.owner');
     }
     return $owner;
   }
diff --git a/core/lib/Drupal/Core/TempStore/SharedTempStore.php b/core/lib/Drupal/Core/TempStore/SharedTempStore.php
index 6bc0340752..70fdef5a1e 100644
--- a/core/lib/Drupal/Core/TempStore/SharedTempStore.php
+++ b/core/lib/Drupal/Core/TempStore/SharedTempStore.php
@@ -5,6 +5,7 @@ namespace Drupal\Core\TempStore;
 use Drupal\Core\DependencyInjection\DependencySerializationTrait;
 use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface;
 use Drupal\Core\Lock\LockBackendInterface;
+use Drupal\Core\Session\AccountProxyInterface;
 use Symfony\Component\HttpFoundation\RequestStack;
 
 /**
@@ -68,6 +69,13 @@ class SharedTempStore {
    */
   protected $owner;
 
+  /**
+   * The current user.
+   *
+   * @var \Drupal\Core\Session\AccountProxyInterface
+   */
+  protected $currentUser;
+
   /**
    * The time to live for items in seconds.
    *
@@ -90,14 +98,28 @@ class SharedTempStore {
    *   The owner key to store along with the data (e.g. a user or session ID).
    * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
    *   The request stack.
+   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
+   *   The current user.
    * @param int $expire
    *   The time to live for items, in seconds.
    */
-  public function __construct(KeyValueStoreExpirableInterface $storage, LockBackendInterface $lock_backend, $owner, RequestStack $request_stack, $expire = 604800) {
+  public function __construct(KeyValueStoreExpirableInterface $storage, LockBackendInterface $lock_backend, $owner, RequestStack $request_stack, $current_user = NULL, $expire = 604800) {
     $this->storage = $storage;
     $this->lockBackend = $lock_backend;
     $this->owner = $owner;
     $this->requestStack = $request_stack;
+    if ($current_user instanceof AccountProxyInterface) {
+      $this->currentUser = $current_user;
+    }
+    else {
+      @trigger_error(__CLASS__ . '::__construct() now requires the current_user service to be injected. See https://www.drupal.org/node/3006268', E_USER_DEPRECATED);
+      $this->currentUser = \Drupal::currentUser();
+      if (is_int($current_user)) {
+        // If the $current_user argument is numeric then this object has been
+        // instantiated with the old constructor signature.
+        $expire = $current_user;
+      }
+    }
     $this->expire = $expire;
   }
 
@@ -150,7 +172,11 @@ class SharedTempStore {
       'data' => $value,
       'updated' => (int) $this->requestStack->getMasterRequest()->server->get('REQUEST_TIME'),
     ];
-    return $this->storage->setWithExpireIfNotExists($key, $value, $this->expire);
+    $set = $this->storage->setWithExpireIfNotExists($key, $value, $this->expire);
+    if ($set) {
+      $this->ensureAnonymousSession();
+    }
+    return $set;
   }
 
   /**
@@ -208,6 +234,7 @@ class SharedTempStore {
       'data' => $value,
       'updated' => (int) $this->requestStack->getMasterRequest()->server->get('REQUEST_TIME'),
     ];
+    $this->ensureAnonymousSession();
     $this->storage->setWithExpire($key, $value, $this->expire);
     $this->lockBackend->release($key);
   }
@@ -279,4 +306,15 @@ class SharedTempStore {
     return FALSE;
   }
 
+  /**
+   * Stores the owner in session if the user is anonymous.
+   *
+   * This method should be called when a value is set.
+   */
+  protected function ensureAnonymousSession() {
+    if ($this->currentUser->isAnonymous()) {
+      $this->requestStack->getCurrentRequest()->getSession()->set('core.tempstore.shared.owner', $this->owner);
+    }
+  }
+
 }
diff --git a/core/lib/Drupal/Core/TempStore/SharedTempStoreFactory.php b/core/lib/Drupal/Core/TempStore/SharedTempStoreFactory.php
index 90e816a7dd..9d0040205b 100644
--- a/core/lib/Drupal/Core/TempStore/SharedTempStoreFactory.php
+++ b/core/lib/Drupal/Core/TempStore/SharedTempStoreFactory.php
@@ -2,9 +2,12 @@
 
 namespace Drupal\Core\TempStore;
 
+use Drupal\Component\Utility\Crypt;
 use Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface;
 use Drupal\Core\Lock\LockBackendInterface;
+use Drupal\Core\Session\AccountProxyInterface;
 use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\HttpFoundation\Session\SessionInterface;
 
 /**
  * Creates a shared temporary storage for a collection.
@@ -32,6 +35,20 @@ class SharedTempStoreFactory {
    */
   protected $requestStack;
 
+  /**
+   * The current user.
+   *
+   * @var \Drupal\Core\Session\AccountProxyInterface
+   */
+  protected $currentUser;
+
+  /**
+   * The session service.
+   *
+   * @var \Symfony\Component\HttpFoundation\Session\SessionInterface
+   */
+  protected $session;
+
   /**
    * The time to live for items in seconds.
    *
@@ -48,13 +65,38 @@ class SharedTempStoreFactory {
    *   The lock object used for this data.
    * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
    *   The request stack.
+   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
+   *   The current user.
+   * @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session
+   *   The session service.
    * @param int $expire
    *   The time to live for items, in seconds.
    */
-  public function __construct(KeyValueExpirableFactoryInterface $storage_factory, LockBackendInterface $lock_backend, RequestStack $request_stack, $expire = 604800) {
+  public function __construct(KeyValueExpirableFactoryInterface $storage_factory, LockBackendInterface $lock_backend, RequestStack $request_stack, $current_user = NULL, SessionInterface $session = NULL, $expire = 604800) {
     $this->storageFactory = $storage_factory;
     $this->lockBackend = $lock_backend;
     $this->requestStack = $request_stack;
+
+    if ($current_user instanceof AccountProxyInterface) {
+      $this->currentUser = $current_user;
+    }
+    else {
+      $this->currentUser = \Drupal::currentUser();
+    }
+    if ($session instanceof SessionInterface) {
+      $this->session = $session;
+    }
+    else {
+      $this->session = \Drupal::service('session');
+    }
+    if (!($current_user instanceof AccountProxyInterface) || !($session instanceof  SessionInterface)) {
+      @trigger_error(__CLASS__ . '::__construct() now requires the current_user and session services to be injected. See https://www.drupal.org/node/3006268', E_USER_DEPRECATED);
+      if (is_int($current_user)) {
+        // If the $current_user argument is numeric then this object has been
+        // instantiated with the old constructor signature.
+        $expire = $current_user;
+      }
+    }
     $this->expire = $expire;
   }
 
@@ -76,12 +118,23 @@ class SharedTempStoreFactory {
     // Use the currently authenticated user ID or the active user ID unless
     // the owner is overridden.
     if (!isset($owner)) {
-      $owner = \Drupal::currentUser()->id() ?: session_id();
+      $owner = $this->currentUser->id();
+      if ($this->currentUser->isAnonymous()) {
+        $has_session = $this->requestStack
+          ->getCurrentRequest()
+          ->hasSession();
+        if (!$has_session) {
+          $this->requestStack->getCurrentRequest()->setSession($this->session);
+          $this->session->start();
+        }
+        // Anonymous users store a random identifier in session.
+        $owner = $this->requestStack->getCurrentRequest()->getSession()->get('core.tempstore.shared.owner', Crypt::randomBytesBase64());
+      }
     }
 
     // Store the data for this collection in the database.
     $storage = $this->storageFactory->get("tempstore.shared.$collection");
-    return new SharedTempStore($storage, $this->lockBackend, $owner, $this->requestStack, $this->expire);
+    return new SharedTempStore($storage, $this->lockBackend, $owner, $this->requestStack, $this->currentUser, $this->expire);
   }
 
 }
diff --git a/core/modules/user/src/SharedTempStoreFactory.php b/core/modules/user/src/SharedTempStoreFactory.php
index c955f07f7a..fe4deb00d3 100644
--- a/core/modules/user/src/SharedTempStoreFactory.php
+++ b/core/modules/user/src/SharedTempStoreFactory.php
@@ -35,12 +35,23 @@ class SharedTempStoreFactory extends CoreSharedTempStoreFactory {
     // Use the currently authenticated user ID or the active user ID unless
     // the owner is overridden.
     if (!isset($owner)) {
-      $owner = \Drupal::currentUser()->id() ?: session_id();
+      $owner = $this->currentUser->id();
+      if ($this->currentUser->isAnonymous()) {
+        $has_session = $this->requestStack
+          ->getCurrentRequest()
+          ->hasSession();
+        if (!$has_session) {
+          $this->requestStack->getCurrentRequest()->setSession($this->session);
+          $this->session->start();
+        }
+        // Anonymous users store a random identifier in session.
+        $owner = $this->requestStack->getCurrentRequest()->getSession()->get('core.tempstore.shared.owner', Crypt::randomBytesBase64());
+      }
     }
 
     // Store the data for this collection in the database.
     $storage = $this->storageFactory->get("user.shared_tempstore.$collection");
-    return new SharedTempStore($storage, $this->lockBackend, $owner, $this->requestStack, $this->expire);
+    return new SharedTempStore($storage, $this->lockBackend, $owner, $this->requestStack, $this->currentUser, $this->expire);
   }
 
 }
diff --git a/core/modules/user/tests/src/Kernel/TempStoreDatabaseTest.php b/core/modules/user/tests/src/Kernel/TempStoreDatabaseTest.php
index 51a3b9f8e7..ce2ea64764 100644
--- a/core/modules/user/tests/src/Kernel/TempStoreDatabaseTest.php
+++ b/core/modules/user/tests/src/Kernel/TempStoreDatabaseTest.php
@@ -3,6 +3,7 @@
 namespace Drupal\Tests\user\Kernel;
 
 use Drupal\Core\KeyValueStore\KeyValueExpirableFactory;
+use Drupal\Core\Session\AccountProxyInterface;
 use Drupal\KernelTests\KernelTestBase;
 use Drupal\user\SharedTempStoreFactory;
 use Drupal\Core\Lock\DatabaseLockBackend;
@@ -73,8 +74,17 @@ class TempStoreDatabaseTest extends KernelTestBase {
    * @expectedDeprecation \Drupal\user\SharedTempStore is scheduled for removal in Drupal 9.0.0. Use \Drupal\Core\TempStore\SharedTempStore instead. See https://www.drupal.org/node/2935639.
    */
   public function testUserTempStore() {
+    // Mock the current user service so that isAnonymous returns FALSE.
+    $current_user = $this->prophesize(AccountProxyInterface::class);
+
     // Create a key/value collection.
-    $factory = new SharedTempStoreFactory(new KeyValueExpirableFactory(\Drupal::getContainer()), new DatabaseLockBackend(Database::getConnection()), $this->container->get('request_stack'));
+    $factory = new SharedTempStoreFactory(
+      new KeyValueExpirableFactory(\Drupal::getContainer()),
+      new DatabaseLockBackend(Database::getConnection()),
+      $this->container->get('request_stack'),
+      $current_user->reveal(),
+      $this->container->get('session')
+    );
     $collection = $this->randomMachineName();
 
     // Create two mock users.
diff --git a/core/modules/user/tests/src/Unit/SharedTempStoreTest.php b/core/modules/user/tests/src/Unit/SharedTempStoreTest.php
index 59a9d8f711..5339e02a64 100644
--- a/core/modules/user/tests/src/Unit/SharedTempStoreTest.php
+++ b/core/modules/user/tests/src/Unit/SharedTempStoreTest.php
@@ -2,11 +2,13 @@
 
 namespace Drupal\Tests\user\Unit;
 
+use Drupal\Core\Session\AccountProxyInterface;
 use Drupal\Tests\UnitTestCase;
 use Drupal\user\SharedTempStore;
 use Drupal\user\TempStoreException;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\HttpFoundation\Session\SessionInterface;
 
 /**
  * @coversDefaultClass \Drupal\user\SharedTempStore
@@ -76,9 +78,12 @@ class SharedTempStoreTest extends UnitTestCase {
     $this->lock = $this->createMock('Drupal\Core\Lock\LockBackendInterface');
     $this->requestStack = new RequestStack();
     $request = Request::createFromGlobals();
+    $session = $this->getMock(SessionInterface::class);
+    $request->setSession($session);
     $this->requestStack->push($request);
+    $current_user = $this->getMock(AccountProxyInterface::class);
 
-    $this->tempStore = new SharedTempStore($this->keyValue, $this->lock, $this->owner, $this->requestStack, 604800);
+    $this->tempStore = new SharedTempStore($this->keyValue, $this->lock, $this->owner, $this->requestStack, $current_user, 604800);
 
     $this->ownObject = (object) [
       'data' => 'test_data',
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 7c18443ef1..cbc9ee3722 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -566,8 +566,10 @@ function user_login_finalize(UserInterface $account) {
   // This is called before hook_user_login() in case one of those functions
   // fails or incorrectly does a redirect which would leave the old session
   // in place.
-  \Drupal::service('session')->migrate();
-  \Drupal::service('session')->set('uid', $account->id());
+  /** @var \Symfony\Component\HttpFoundation\Session\Session $session */
+  $session = \Drupal::service('session');
+  $session->migrate(TRUE);
+  $session->set('uid', $account->id());
   \Drupal::moduleHandler()->invokeAll('user_login', [$account]);
 }
 
diff --git a/core/tests/Drupal/KernelTests/Core/TempStore/TempStoreDatabaseTest.php b/core/tests/Drupal/KernelTests/Core/TempStore/TempStoreDatabaseTest.php
index 929bfbec7d..1b6ac6abc1 100644
--- a/core/tests/Drupal/KernelTests/Core/TempStore/TempStoreDatabaseTest.php
+++ b/core/tests/Drupal/KernelTests/Core/TempStore/TempStoreDatabaseTest.php
@@ -3,6 +3,7 @@
 namespace Drupal\KernelTests\Core\TempStore;
 
 use Drupal\Core\KeyValueStore\KeyValueExpirableFactory;
+use Drupal\Core\Session\AccountProxyInterface;
 use Drupal\KernelTests\KernelTestBase;
 use Drupal\Core\TempStore\SharedTempStoreFactory;
 use Drupal\Core\Lock\DatabaseLockBackend;
@@ -64,7 +65,15 @@ class TempStoreDatabaseTest extends KernelTestBase {
   public function testSharedTempStore() {
     // Create a key/value collection.
     $database = Database::getConnection();
-    $factory = new SharedTempStoreFactory(new KeyValueExpirableFactory(\Drupal::getContainer()), new DatabaseLockBackend($database), $this->container->get('request_stack'));
+    // Mock the current user service so that isAnonymous returns FALSE.
+    $current_user = $this->prophesize(AccountProxyInterface::class);
+    $factory = new SharedTempStoreFactory(
+      new KeyValueExpirableFactory(\Drupal::getContainer()),
+      new DatabaseLockBackend($database),
+      $this->container->get('request_stack'),
+      $current_user->reveal(),
+      $this->container->get('session')
+    );
     $collection = $this->randomMachineName();
 
     // Create two mock users.
diff --git a/core/tests/Drupal/Tests/Core/TempStore/SharedTempStoreFactoryTest.php b/core/tests/Drupal/Tests/Core/TempStore/SharedTempStoreFactoryTest.php
new file mode 100644
index 0000000000..2874b35c83
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/TempStore/SharedTempStoreFactoryTest.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace Drupal\Tests\Core\TempStore;
+
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface;
+use Drupal\Core\Lock\LockBackendInterface;
+use Drupal\Core\Session\AccountProxyInterface;
+use Drupal\Core\TempStore\SharedTempStoreFactory;
+use Drupal\Tests\UnitTestCase;
+use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\HttpFoundation\Session\SessionInterface;
+
+/**
+ * @coversDefaultClass \Drupal\Core\TempStore\SharedTempStoreFactory
+ * @group TempStore
+ */
+class SharedTempStoreFactoryTest extends UnitTestCase {
+
+  /**
+   * @group legacy
+   * @expectedDeprecation Drupal\Core\TempStore\SharedTempStoreFactory::__construct() now requires the current_user and session services to be injected. See https://www.drupal.org/node/3006268
+   */
+  public function testLegacyConstructor() {
+    $container = new ContainerBuilder();
+    $current_user = $this->prophesize(AccountProxyInterface::class)->reveal();
+    $session = $this->prophesize(SessionInterface::class)->reveal();
+    $container->set('current_user', $current_user);
+    $container->set('session', $session);
+    \Drupal::setContainer($container);
+
+    $key_value_factory = $this->prophesize(KeyValueExpirableFactoryInterface::class)->reveal();
+    $lock = $this->prophesize(LockBackendInterface::class)->reveal();
+    $request_stack = $this->prophesize(RequestStack::class)->reveal();
+    $store = new SharedTempStoreFactory($key_value_factory, $lock, $request_stack, 1000);
+
+    $reflection_class = new \ReflectionClass(SharedTempStoreFactory::class);
+
+    $current_user_property = $reflection_class->getProperty('currentUser');
+    $current_user_property->setAccessible(TRUE);
+    $this->assertSame($current_user, $current_user_property->getValue($store));
+
+    $expire_property = $reflection_class->getProperty('expire');
+    $expire_property->setAccessible(TRUE);
+    $this->assertSame(1000, $expire_property->getValue($store));
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/TempStore/SharedTempStoreTest.php b/core/tests/Drupal/Tests/Core/TempStore/SharedTempStoreTest.php
index 3e519d184c..719a4686e0 100644
--- a/core/tests/Drupal/Tests/Core/TempStore/SharedTempStoreTest.php
+++ b/core/tests/Drupal/Tests/Core/TempStore/SharedTempStoreTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\Core\TempStore;
 
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Core\Session\AccountProxyInterface;
 use Drupal\Core\TempStore\Lock;
 use Drupal\Tests\UnitTestCase;
 use Drupal\Core\TempStore\SharedTempStore;
@@ -9,6 +11,7 @@ use Drupal\Core\TempStore\TempStoreException;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\HttpFoundation\Session\SessionInterface;
 
 /**
  * @coversDefaultClass \Drupal\Core\TempStore\SharedTempStore
@@ -75,9 +78,12 @@ class SharedTempStoreTest extends UnitTestCase {
     $this->lock = $this->createMock('Drupal\Core\Lock\LockBackendInterface');
     $this->requestStack = new RequestStack();
     $request = Request::createFromGlobals();
+    $session = $this->getMock(SessionInterface::class);
+    $request->setSession($session);
     $this->requestStack->push($request);
+    $current_user = $this->getMock(AccountProxyInterface::class);
 
-    $this->tempStore = new SharedTempStore($this->keyValue, $this->lock, $this->owner, $this->requestStack, 604800);
+    $this->tempStore = new SharedTempStore($this->keyValue, $this->lock, $this->owner, $this->requestStack, $current_user, 604800);
 
     $this->ownObject = (object) [
       'data' => 'test_data',
@@ -411,4 +417,25 @@ class SharedTempStoreTest extends UnitTestCase {
     $this->assertSame($unserializable_request, $request_stack->pop());
   }
 
+  /**
+   * @group legacy
+   * @expectedDeprecation Drupal\Core\TempStore\SharedTempStore::__construct() now requires the current_user service to be injected. See https://www.drupal.org/node/3006268
+   */
+  public function testLegacyConstructor() {
+    $container = new ContainerBuilder();
+    $current_user = $this->getMock(AccountProxyInterface::class);
+    $container->set('current_user', $current_user);
+    \Drupal::setContainer($container);
+    $store = new SharedTempStore($this->keyValue, $this->lock, 2, $this->requestStack, 1000);
+    $reflection_class = new \ReflectionClass(SharedTempStore::class);
+
+    $current_user_property = $reflection_class->getProperty('currentUser');
+    $current_user_property->setAccessible(TRUE);
+    $this->assertSame($current_user, $current_user_property->getValue($store));
+
+    $expire_property = $reflection_class->getProperty('expire');
+    $expire_property->setAccessible(TRUE);
+    $this->assertSame(1000, $expire_property->getValue($store));
+  }
+
 }
