diff --git a/core/core.services.yml b/core/core.services.yml
index 802d143..1071c6d 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -707,11 +707,10 @@ services:
       - { name: event_subscriber }
     arguments: ['@authentication']
   current_user:
-    class: Drupal\Core\Session\AccountInterface
-    factory_method: authenticate
-    factory_service: authentication
-    arguments: ['@request']
-    synchronized: true
+    class: Drupal\Core\Authentication\AccountProxy
+    arguments: ['@authentication']
+    calls:
+      - [setRequest, ['@?request=']]
   asset.css.collection_renderer:
     class: Drupal\Core\Asset\CssCollectionRenderer
     arguments: [ '@state' ]
diff --git a/core/lib/Drupal/Core/Authentication/AccountProxy.php b/core/lib/Drupal/Core/Authentication/AccountProxy.php
new file mode 100644
index 0000000..b67e9d8
--- /dev/null
+++ b/core/lib/Drupal/Core/Authentication/AccountProxy.php
@@ -0,0 +1,189 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Authentication\AccountProxy.
+ */
+
+namespace Drupal\Core\Authentication;
+
+use Drupal\Core\Session\AccountInterface;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * A proxied implementation of AccountInterface.
+ */
+class AccountProxy implements AccountInterface {
+
+  /**
+   * The current request.
+   *
+   * @var \Symfony\Component\HttpFoundation\Request
+   */
+  protected $request;
+
+  /**
+   * The authentication manager.
+   *
+   * @var \Drupal\Core\Authentication\AuthenticationManagerInterface
+   */
+  protected $authenticationManager;
+
+  /**
+   * The instantiated account.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $account;
+
+  /**
+   * Constructs a new AccountProxy.
+   *
+   * @param \Drupal\Core\Authentication\AuthenticationManagerInterface $authentication_manager
+   *   The authentication manager.
+   */
+  public function __construct(AuthenticationManagerInterface $authentication_manager) {
+    $this->authenticationManager = $authentication_manager;
+  }
+
+  /**
+   * Sets the current request.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The current request.
+   */
+  public function setRequest(Request $request) {
+    $this->request = $request;
+    // Reset the current user to ensure that new calls will return the correct
+    // user based on the request.
+    $this->account = NULL;
+  }
+
+  /**
+   * Set the current wrapped account.
+   *
+   * @param \Drupal\Core\Session\AccountInterface
+   *   The current account.
+   */
+  public function setAccount(AccountInterface $account) {
+    // If the passed account is already proxied, use the actual account instead
+    // to prevent loops.
+    if ($account instanceof static) {
+      $account = $account->getAccount();
+    }
+    $this->account = $account;
+  }
+
+  /**
+   * Gets the current account.
+   *
+   * @return \Drupal\Core\Session\AccountInterface
+   *   The current account.
+   */
+  protected function getAccount() {
+    if (!isset($this->account)) {
+      $this->account = $this->authenticationManager->authenticate($this->request);
+    }
+    return $this->account;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function id() {
+    return $this->getAccount()->id();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getRoles() {
+    return $this->getAccount()->getRoles();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function hasPermission($permission) {
+    return $this->getAccount()->hasPermission($permission);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getSessionId() {
+    return $this->getAccount()->getSessionId();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getSecureSessionId() {
+    return $this->getAccount()->getSecureSessionId();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getSessionData() {
+    return $this->getAccount()->getSessionData();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isAuthenticated() {
+    return $this->getAccount()->isAuthenticated();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isAnonymous() {
+    return $this->getAccount()->isAnonymous();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPreferredLangcode($default = NULL) {
+    return $this->getAccount()->getPreferredLangcode($default);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPreferredAdminLangcode($default = NULL) {
+    return $this->getAccount()->getPreferredAdminLangcode($default);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getUsername() {
+    return $this->getAccount()->getUsername();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getEmail() {
+    return $this->getAccount()->getEmail();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getTimeZone() {
+    return $this->getAccount()->getTimeZone();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getLastAccessedTime() {
+    return $this->getAccount()->getLastAccessedTime();
+  }
+
+}
+
diff --git a/core/lib/Drupal/Core/Authentication/AuthenticationManagerInterface.php b/core/lib/Drupal/Core/Authentication/AuthenticationManagerInterface.php
index b547edd..0b4c0ff 100644
--- a/core/lib/Drupal/Core/Authentication/AuthenticationManagerInterface.php
+++ b/core/lib/Drupal/Core/Authentication/AuthenticationManagerInterface.php
@@ -10,7 +10,7 @@
 /**
  * Defines an interface for authentication managers.
  */
-interface AuthenticationManagerInterface {
+interface AuthenticationManagerInterface extends AuthenticationProviderInterface {
 
   /**
    * Returns the service id of the default authentication provider.
@@ -19,4 +19,5 @@
    *   The service id of the default authentication provider.
    */
   public function defaultProviderId();
+
 }
diff --git a/core/lib/Drupal/Core/Routing/Enhancer/AuthenticationEnhancer.php b/core/lib/Drupal/Core/Routing/Enhancer/AuthenticationEnhancer.php
index 6e577b9..14b2716 100644
--- a/core/lib/Drupal/Core/Routing/Enhancer/AuthenticationEnhancer.php
+++ b/core/lib/Drupal/Core/Routing/Enhancer/AuthenticationEnhancer.php
@@ -54,7 +54,7 @@ public function enhance(array $defaults, Request $request) {
       if (!in_array($auth_provider_triggered, $auth_providers)) {
         $anonymous_user = drupal_anonymous_user();
 
-        $this->container->set('current_user', $anonymous_user, 'request');
+        $this->container->get('current_user')->setAccount($anonymous_user);
 
         // The global $user object is included for backward compatibility only
         // and should be considered deprecated.
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php
index 0178a25..19f5035 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php
@@ -120,7 +120,7 @@ public function testNodeHandler() {
 
     // Test as a non-admin.
     $normal_user = $this->drupalCreateUser(array('access content'));
-    $this->container->set('current_user', $normal_user);
+    \Drupal::currentUser()->setAccount($normal_user);
     $referenceable_tests = array(
       array(
         'arguments' => array(
@@ -172,7 +172,7 @@ public function testNodeHandler() {
 
     // Test as an admin.
     $admin_user = $this->drupalCreateUser(array('access content', 'bypass node access'));
-    $this->container->set('current_user', $admin_user);
+    \Drupal::currentUser()->setAccount($admin_user);
     $referenceable_tests = array(
       array(
         'arguments' => array(
@@ -266,7 +266,7 @@ public function testUserHandler() {
     }
 
     // Test as a non-admin.
-    $this->container->set('current_user', $users['non_admin']);
+    \Drupal::currentUser()->setAccount($users['non_admin']);
     $referenceable_tests = array(
       array(
         'arguments' => array(
@@ -305,7 +305,7 @@ public function testUserHandler() {
     );
     $this->assertReferenceable($instance, $referenceable_tests, 'User handler');
 
-    $this->container->set('current_user', $users['admin']);
+    \Drupal::currentUser()->setAccount($users['admin']);
     $referenceable_tests = array(
       array(
         'arguments' => array(
@@ -447,7 +447,7 @@ public function testCommentHandler() {
 
     // Test as a non-admin.
     $normal_user = $this->drupalCreateUser(array('access content', 'access comments'));
-    $this->container->set('current_user', $normal_user);
+    \Drupal::currentUser()->setAccount($normal_user);
     $referenceable_tests = array(
       array(
         'arguments' => array(
@@ -486,7 +486,7 @@ public function testCommentHandler() {
 
     // Test as a comment admin.
     $admin_user = $this->drupalCreateUser(array('access content', 'access comments', 'administer comments'));
-    $this->container->set('current_user', $admin_user);
+    \Drupal::currentUser()->setAccount($admin_user);
     $referenceable_tests = array(
       array(
         'arguments' => array(
@@ -504,7 +504,7 @@ public function testCommentHandler() {
 
     // Test as a node and comment admin.
     $admin_user = $this->drupalCreateUser(array('access content', 'access comments', 'administer comments', 'bypass node access'));
-    $this->container->set('current_user', $admin_user);
+    \Drupal::currentUser()->setAccount($admin_user);
     $referenceable_tests = array(
       array(
         'arguments' => array(
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php
index fbd4461..06f0a69 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php
@@ -120,7 +120,7 @@ public function testSort() {
 
     // Test as a non-admin.
     $normal_user = $this->drupalCreateUser(array('access content'));
-    $this->container->set('current_user', $normal_user);
+    \Drupal::currentUser()->setAccount($normal_user);
 
     $handler = $this->container->get('plugin.manager.entity_reference.selection')->getSelectionHandler($instance);
 
diff --git a/core/modules/file/lib/Drupal/file/Tests/FileManagedUnitTestBase.php b/core/modules/file/lib/Drupal/file/Tests/FileManagedUnitTestBase.php
index 324b1b5..c9ec86d 100644
--- a/core/modules/file/lib/Drupal/file/Tests/FileManagedUnitTestBase.php
+++ b/core/modules/file/lib/Drupal/file/Tests/FileManagedUnitTestBase.php
@@ -37,7 +37,7 @@ function setUp() {
     $user = entity_create('user', array('uid' => 1, 'name' => $this->randomName()));
     $user->enforceIsNew();
     $user->save();
-    $this->container->set('current_user', $user);
+    \Drupal::currentUser()->setAccount($user);
   }
 
   /**
diff --git a/core/modules/file/lib/Drupal/file/Tests/ValidatorTest.php b/core/modules/file/lib/Drupal/file/Tests/ValidatorTest.php
index f054602..398860c 100644
--- a/core/modules/file/lib/Drupal/file/Tests/ValidatorTest.php
+++ b/core/modules/file/lib/Drupal/file/Tests/ValidatorTest.php
@@ -133,7 +133,7 @@ function testFileValidateSize() {
     $user = entity_create('user', array('uid' => 2, 'name' => $this->randomName()));
     $user->enforceIsNew();
     $user->save();
-    $this->container->set('current_user', $user);
+    \Drupal::currentUser()->setAccount($user);
 
     // Create a file with a size of 1000 bytes, and quotas of only 1 byte.
     $file = entity_create('file', array('filesize' => 1000));
diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php
index c36b009..0f9c4fc 100644
--- a/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php
+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php
@@ -206,7 +206,7 @@ function testTypedDataAPI() {
 
     // Test with anonymous user.
     $user = drupal_anonymous_user();
-    $this->container->set('current_user', $user);
+    \Drupal::currentUser()->setAccount($user);
 
     $expected_available_options = array(
       'filtered_html' => 'Filtered HTML',
@@ -245,7 +245,7 @@ function testTypedDataAPI() {
     $this->assertFilterFormatViolation($violations, 'filtered_html');
 
     // Set user with access to 'filtered_html' format.
-    $this->container->set('current_user', $filtered_html_user);
+    \Drupal::currentUser()->setAccount($filtered_html_user);
     $violations = $data->validate();
     $this->assertEqual(count($violations), 0, "No validation violation for accessible format 'filtered_html' found.");
 
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
index 1ab979f..5ca1d69 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -1090,7 +1090,7 @@ private function prepareEnvironment() {
 
     // Run all tests as a anonymous user by default, web tests will replace that
     // during the test set up.
-    $this->container->set('current_user', drupal_anonymous_user());
+    \Drupal::currentUser()->setAccount(drupal_anonymous_user());
 
     \Drupal::setContainer($this->container);
 
@@ -1149,7 +1149,7 @@ protected function rebuildContainer($environment = 'testing') {
     $this->container = \Drupal::getContainer();
     // The current user is set in TestBase::prepareEnvironment().
     $this->container->set('request', $request);
-    $this->container->set('current_user', \Drupal::currentUser());
+    $this->container->get('current_user')->setAccount(\Drupal::currentUser());
   }
 
   /**
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index 30a6280..b7b260b 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -675,7 +675,7 @@ protected function drupalLogin(AccountInterface $account) {
     $pass = $this->assert($this->drupalUserIsLoggedIn($account), format_string('User %name successfully logged in.', array('%name' => $account->getUsername())), 'User login');
     if ($pass) {
       $this->loggedInUser = $account;
-      $this->container->set('current_user', $account);
+      $this->container->get('current_user')->setAccount($account);
       // @todo Temporary workaround for not being able to use synchronized
       //   services in non dumped container.
       $this->container->get('access_subscriber')->setCurrentUser($account);
@@ -723,7 +723,7 @@ protected function drupalLogout() {
       // @see WebTestBase::drupalUserIsLoggedIn()
       unset($this->loggedInUser->session_id);
       $this->loggedInUser = FALSE;
-      $this->container->set('current_user', drupal_anonymous_user());
+      $this->container->get('current_user')->setAccount(drupal_anonymous_user());
     }
   }
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/FormCacheTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/FormCacheTest.php
index 0e6d629..6b17e88 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Form/FormCacheTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/FormCacheTest.php
@@ -46,7 +46,7 @@ public function setUp() {
    * Tests the form cache with a logged-in user.
    */
   function testCacheToken() {
-    $this->container->set('current_user', new UserSession(array('uid' => 1)));
+    $this->container->get('current_user')->setAccount(new UserSession(array('uid' => 1)));
     form_set_cache($this->form_build_id, $this->form, $this->form_state);
 
     $cached_form_state = form_state_defaults();
diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/FunctionsTest.php b/core/modules/system/lib/Drupal/system/Tests/Theme/FunctionsTest.php
index 586e1eb..5013e5a 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Theme/FunctionsTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Theme/FunctionsTest.php
@@ -243,7 +243,7 @@ function testLinks() {
     $this->assertThemeOutput('links', $variables, $expected);
 
     // Verify the data- attributes for setting the "active" class on links.
-    $this->container->set('current_user', new UserSession(array('uid' => 1)));
+    $this->container->get('current_user')->setAccount(new UserSession(array('uid' => 1)));
     $variables['set_active_class'] = TRUE;
     $expected_links = '';
     $expected_links .= '<ul id="somelinks">';
diff --git a/core/modules/system/tests/modules/router_test_directory/lib/Drupal/router_test/TestContent.php b/core/modules/system/tests/modules/router_test_directory/lib/Drupal/router_test/TestContent.php
index 57a1a85..6559c70 100644
--- a/core/modules/system/tests/modules/router_test_directory/lib/Drupal/router_test/TestContent.php
+++ b/core/modules/system/tests/modules/router_test_directory/lib/Drupal/router_test/TestContent.php
@@ -58,9 +58,9 @@ public function test11() {
   }
 
   public function testAccount(UserInterface $user) {
-    $current_user = $this->currentUser();
-    \Drupal::getContainer()->set('current_user', $user);
-    return $current_user->getUsername() . ':' . $user->getUsername();
+    $current_user_name = $this->currentUser()->getUsername();
+    $this->currentUser()->setAccount($user);
+    return $current_user_name . ':' . $user->getUsername();
   }
 
   /**
