diff --git a/core/authorize.php b/core/authorize.php
index f347ba5..fe39394 100644
--- a/core/authorize.php
+++ b/core/authorize.php
@@ -48,10 +48,12 @@ function authorize_access_denied_page() {
  * The killswitch in settings.php overrides all else, otherwise, the user must
  * have access to the 'administer software updates' permission.
  *
- * @return
+ * @return bool
  *   TRUE if the current user can run authorize.php, and FALSE if not.
  */
 function authorize_access_allowed() {
+  require_once DRUPAL_ROOT . '/' . settings()->get('session_inc', 'core/includes/session.inc');
+  drupal_session_initialize();
   return settings()->get('allow_authorize_operations', TRUE) && user_access('administer software updates');
 }
 
@@ -65,7 +67,7 @@ function authorize_access_allowed() {
 
 // We prepare only a minimal bootstrap. This includes the database and
 // variables, however, so we have access to the class autoloader.
-drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION);
+drupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES);
 
 // This must go after drupal_bootstrap(), which unsets globals!
 global $conf;
diff --git a/core/core.services.yml b/core/core.services.yml
index 50775db..d6708e0 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -519,3 +519,22 @@ services:
     class: Zend\Feed\Writer\Extension\Threading\Renderer\Entry
   feed.writer.wellformedwebrendererentry:
     class: Zend\Feed\Writer\Extension\WellFormedWeb\Renderer\Entry
+  authentication:
+    class: Drupal\Core\Authentication\AuthenticationManager
+  authentication.cookie:
+    class: Drupal\Core\Authentication\Provider\Cookie
+    tags:
+      - { name: authentication_provider, priority: 0 }
+  authentication.http_basic:
+    class: Drupal\Core\Authentication\Provider\HttpBasic
+    tags:
+      - { name: authentication_provider, priority: 100 }
+  authentication_subscriber:
+    class: Drupal\Core\EventSubscriber\AuthenticationSubscriber
+    tags:
+      - { name: event_subscriber }
+    arguments: ['@authentication']
+  access_check.authentication_provider:
+    class: Drupal\Core\Access\AuthenticationProviderAccessCheck
+    tags:
+      - { name: access_check }
diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index cf0e3dd..226bfbf 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -158,11 +158,6 @@
 const DRUPAL_BOOTSTRAP_VARIABLES = 4;
 
 /**
- * Sixth bootstrap phase: initialize session handling.
- */
-const DRUPAL_BOOTSTRAP_SESSION = 5;
-
-/**
  * Eighth bootstrap phase: load code for subsystems and modules.
  */
 const DRUPAL_BOOTSTRAP_CODE = 6;
@@ -1770,7 +1765,6 @@ function drupal_anonymous_user() {
  *   - DRUPAL_BOOTSTRAP_PAGE_CACHE: Tries to serve a cached page.
  *   - DRUPAL_BOOTSTRAP_DATABASE: Initializes the database layer.
  *   - DRUPAL_BOOTSTRAP_VARIABLES: Initializes the variable system.
- *   - DRUPAL_BOOTSTRAP_SESSION: Initializes session handling.
  *   - DRUPAL_BOOTSTRAP_CODE: Loads code for subsystems and modules.
  *   - DRUPAL_BOOTSTRAP_FULL: Fully loads Drupal. Validates and fixes input
  *     data.
@@ -1789,7 +1783,6 @@ function drupal_bootstrap($phase = NULL, $new_phase = TRUE) {
     DRUPAL_BOOTSTRAP_PAGE_CACHE,
     DRUPAL_BOOTSTRAP_DATABASE,
     DRUPAL_BOOTSTRAP_VARIABLES,
-    DRUPAL_BOOTSTRAP_SESSION,
     DRUPAL_BOOTSTRAP_CODE,
     DRUPAL_BOOTSTRAP_FULL,
   );
@@ -1839,11 +1832,6 @@ function drupal_bootstrap($phase = NULL, $new_phase = TRUE) {
           _drupal_bootstrap_variables();
           break;
 
-        case DRUPAL_BOOTSTRAP_SESSION:
-          require_once DRUPAL_ROOT . '/' . settings()->get('session_inc', 'core/includes/session.inc');
-          drupal_session_initialize();
-          break;
-
         case DRUPAL_BOOTSTRAP_CODE:
           require_once __DIR__ . '/common.inc';
           _drupal_bootstrap_code();
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 1ecd819..5f2ccc7 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -1746,6 +1746,8 @@ function install_load_profile(&$install_state) {
  */
 function install_bootstrap_full() {
   drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
+  require_once DRUPAL_ROOT . '/' . settings()->get('session_inc', 'core/includes/session.inc');
+  drupal_session_initialize();
 }
 
 /**
diff --git a/core/lib/Drupal/Core/Access/AuthenticationProviderAccessCheck.php b/core/lib/Drupal/Core/Access/AuthenticationProviderAccessCheck.php
new file mode 100644
index 0000000..4b32162
--- /dev/null
+++ b/core/lib/Drupal/Core/Access/AuthenticationProviderAccessCheck.php
@@ -0,0 +1,52 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Access\AuthenticationProviderAccessCheck.
+ */
+
+namespace Drupal\Core\Access;
+
+use Symfony\Component\Routing\Route;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Access check based on authentication mechanisms.
+ */
+class AuthenticationProviderAccessCheck implements AccessCheckInterface {
+
+  /**
+   * {@inheritdoc}
+   *
+   * This access check applies to every route.
+   */
+  public function applies(Route $route) {
+    return TRUE;
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * A route can have a list of allowed authentication mechanism. Check if the
+   * triggered provider is part of this list.
+   */
+  public function access(Route $route, Request $request) {
+    $auth_provider_triggered = $request->attributes->get('_authentication_provider');
+    if (!empty($auth_provider_triggered)) {
+      $allowed_auth_providers = $route->getOption('_auth');
+      if (empty($allowed_auth_providers)) {
+        return NULL;
+      }
+      $check = in_array($auth_provider_triggered, $allowed_auth_providers);
+
+      // Set user as anonymous as he should not be logged in because he logged in
+      // with not allowed authentication provider.
+      if ($check == FALSE) {
+        global $user;
+        $user = drupal_anonymous_user();
+      }
+
+      return $check;
+    }
+  }
+}
diff --git a/core/lib/Drupal/Core/Authentication/AuthenticationManager.php b/core/lib/Drupal/Core/Authentication/AuthenticationManager.php
new file mode 100644
index 0000000..bcc17e4
--- /dev/null
+++ b/core/lib/Drupal/Core/Authentication/AuthenticationManager.php
@@ -0,0 +1,191 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Authentication\AuthenticationManager.
+ */
+
+namespace Drupal\Core\Authentication;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Cmf\Component\Routing\RouteObjectInterface;
+use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
+
+/**
+ * Manager for authentication.
+ *
+ * On each request, let all authentication provider to authenticate the user.
+ * The provider are iterated according to their priority and the first provider
+ * detecting credentials for his method will become the triggered provider. No
+ * further provider will get triggered.
+ * If no provider felt responsible the manager assumes that the least
+ * prioritized should have and therefore is the triggered provider and the user
+ * is set to anonymous.
+ */
+class AuthenticationManager implements AuthenticationProviderInterface {
+
+  /**
+   * Array of all registered authentication providers.
+   *
+   * @var AuthenticationProviderInterface[]
+   */
+  protected $providers;
+
+  /**
+   * Priority array off all registered authentication providers.
+   *
+   * This is used to sort the providers based on their priority.
+   *
+   * @var int[]
+   *
+   * @see AuthenticationManager::compareProviderPriority()
+   * @see AuthenticationManager::addProvider()
+   */
+  protected $providerPriorities;
+
+  /**
+   * Id of the provider that authenticated the user.
+   *
+   * @var string
+   */
+  protected $triggeredProvider = '';
+
+  /**
+   * The authenticated user.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $account;
+
+  /**
+   * Add provider to the array of registered providers.
+   *
+   * @param string $provider_id
+   *   Identifier of the provider.
+   * @param AuthenticationProviderInterface $provider
+   *   The provider object.
+   * @param int $priority
+   *   The providers priority.
+   */
+  public function addProvider($provider_id, AuthenticationProviderInterface $provider, $priority = 0) {
+    $provider_id = substr($provider_id, strlen('authentication.'));
+    $this->providers[$provider_id] = $provider;
+    $this->providerPriorities[$provider_id] = $priority;
+  }
+
+  /**
+   * Compares providers by their priority.
+   *
+   * This is a uksort() callback allowing to sort the providers by their keys
+   * based on their priorities.
+   *
+   * @param string $a
+   *   A provider key.
+   * @param string $b
+   *   Another provider key.
+   *
+   * @return int
+   *   0  - If both providers have the same priority.
+   *   1  - If provider A has lower priority than B.
+   *   -1 - If provider A has higher priority than A.
+   */
+  public function compareProviderPriority($a, $b) {
+    $priority_a = isset($this->providerPriorities[$a]) ? $this->providerPriorities[$a] : 0;
+    $priority_b = isset($this->providerPriorities[$b]) ? $this->providerPriorities[$b] : 0;
+    if ($priority_a == $priority_b) {
+      return 0;
+    }
+    return ($priority_a > $priority_b) ? -1 : 1;
+  }
+
+  /**
+   * Authenticate user.
+   *
+   * Iterate the available providers according th their priority.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The request object.
+   *
+   * @return \Drupal\Core\Session\AccountInterface
+   *   The account interface of the authenticated user. Defaults to a anonymous.
+   */
+  public function authenticate(Request $request) {
+    global $user;
+
+    // Ensure providers get triggered according to their priority.
+    uksort($this->providers, array($this, 'compareProviderPriority'));
+
+    // Iterate the availlable providers.
+    foreach ($this->providers as $provider_id => $provider) {
+      // Trigger authentication.
+      $account = $provider->authenticate($request);
+
+      // Provider felt responsible for this request.
+      if ($account !== NULL) {
+        $this->account = $account;
+        $this->triggeredProvider = $provider_id;
+        break;
+      }
+    }
+
+    // No provider returned a valid account - assume anonymous.
+    if (!$this->account) {
+      $this->account = drupal_anonymous_user();
+    }
+
+    // No provider felt responsible – assume the one with the least priority
+    // should have.
+    if (!$this->triggeredProvider) {
+      end($this->providers);
+      $this->triggeredProvider = key($this->providers);
+    }
+
+    // Set the global user to the account returned by the triggered provider.
+    $user = $this->account;
+
+    // Save the ID of the triggered provider to the request so that it can be
+    // accessed in Drupal\Core\Access\AuthenticationProviderAccessCheck.
+    $request->attributes->set('_authentication_provider', $this->triggeredProvider);
+
+    return $this->account;
+  }
+
+  /**
+   * Do clean up.
+   *
+   * Allow the triggered provider to clean up before the response is sent, e.g.
+   * trigger a session commit.
+   *
+   * @param Request $request
+   *   The request object.
+   *
+   * @see Drupal\Core\Authentication\Provider\Cookie::cleanup()
+   */
+  public function cleanup(Request $request) {
+    if (empty($this->providers[$this->triggeredProvider])) {
+      return;
+    }
+    $this->providers[$this->triggeredProvider]->cleanup($request);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function handleException(GetResponseForExceptionEvent $event) {
+    $request = $event->getRequest();
+    $route = $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT);
+    if (empty($route)) {
+      return;
+    }
+    $allowed_auth_providers = $route->getOption('_auth');
+    foreach ($this->providers as $provider_id => $provider) {
+      if (!in_array($provider_id, $allowed_auth_providers)) {
+        continue;
+      }
+
+      if (NULL !== $provider->handleException($event)) {
+        break;
+      }
+    }
+  }
+}
diff --git a/core/lib/Drupal/Core/Authentication/AuthenticationProviderInterface.php b/core/lib/Drupal/Core/Authentication/AuthenticationProviderInterface.php
new file mode 100644
index 0000000..c2557d4
--- /dev/null
+++ b/core/lib/Drupal/Core/Authentication/AuthenticationProviderInterface.php
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Authentication\AuthenticationProviderInterface.
+ */
+
+namespace Drupal\Core\Authentication;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
+
+/**
+ * Interface for authentication providers.
+ */
+interface AuthenticationProviderInterface {
+
+  /**
+   * Authenticate user.
+   *
+   * This method called early on KernelEvents::REQUEST event.
+   *
+   * @param Request $request
+   *   The request object.
+   *
+   * @return \Drupal\Core\Session\AccountInterface|FALSE|NULL
+   *   AccountInterface - in case of a successful authentication.
+   *   FALSE - in case we had credentials for authentication but failed.
+   *   NULL - no authentication credentials were found.
+   */
+  public function authenticate(Request $request);
+
+  /**
+   * Do cleanup.
+   *
+   * Allow the authentication provider to clean up before the response is sent.
+   * This is uses for instance in Drupal\Core\Authentication\Provider\Cookie to
+   * ensure the session gets committed.
+   *
+   * @param Request $request
+   *   The request object.
+   */
+  public function cleanup(Request $request);
+
+
+  /**
+   * Handle exception.
+   *
+   * In case exception has happened we allow authentication providers react.
+   * Used in \Drupal\Core\Authentication\Provider\HttpBasic to set up headers to
+   * prompt login.
+   *
+   * @param GetResponseForExceptionEvent $event
+   *
+   * @return bool
+   *   TRUE - exception handled. No need to run through other providers.
+   *   FALSE - no actions have been done. Run through other providers.
+   */
+  public function handleException(GetResponseForExceptionEvent $event);
+}
diff --git a/core/lib/Drupal/Core/Authentication/Provider/Cookie.php b/core/lib/Drupal/Core/Authentication/Provider/Cookie.php
new file mode 100644
index 0000000..657599f
--- /dev/null
+++ b/core/lib/Drupal/Core/Authentication/Provider/Cookie.php
@@ -0,0 +1,52 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Authentication\Provider\Cookie.
+ */
+
+namespace Drupal\Core\Authentication\Provider;
+
+use Drupal\Core\Authentication\AuthenticationProviderInterface;
+use Symfony\Component\HttpFoundation\RedirectResponse;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Cookie based authentication provider.
+ */
+class Cookie implements AuthenticationProviderInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function authenticate(Request $request) {
+    global $user;
+    require_once DRUPAL_ROOT . '/' . settings()->get('session_inc', 'core/includes/session.inc');
+    drupal_session_initialize();
+    if (drupal_session_started()) {
+      return $user;
+    }
+    return NULL;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function cleanup(Request $request) {
+    drupal_session_commit();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function handleException(GetResponseForExceptionEvent $event) {
+    $exception = $event->getException();
+    if (user_is_anonymous() && get_class($exception) == 'Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException') {
+      $event->setResponse(new RedirectResponse(url('user/login', array('absolute' => TRUE))));
+      return TRUE;
+    }
+    return FALSE;
+  }
+}
diff --git a/core/lib/Drupal/Core/Authentication/Provider/HttpBasic.php b/core/lib/Drupal/Core/Authentication/Provider/HttpBasic.php
new file mode 100644
index 0000000..b2508d5
--- /dev/null
+++ b/core/lib/Drupal/Core/Authentication/Provider/HttpBasic.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Authentication\Provider\HttpBasic.
+ */
+
+namespace Drupal\Core\Authentication\Provider;
+
+use Drupal\Core\Authentication\AuthenticationProviderInterface;
+use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
+use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * HTTP Basic authentication provider.
+ */
+class HttpBasic implements AuthenticationProviderInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function authenticate(Request $request) {
+    $username = $request->headers->get('PHP_AUTH_USER');
+    $password = $request->headers->get('PHP_AUTH_PW');
+    if ($username && $password) {
+      $uid = user_authenticate($username, $password);
+      if ($uid) {
+        return user_load($uid);
+      }
+      return FALSE;
+    }
+    return NULL;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function cleanup(Request $request) {}
+
+  /**
+   * {@inheritdoc}
+   */
+  public function handleException(GetResponseForExceptionEvent $event) {
+    $exception = $event->getException();
+    if (user_is_anonymous() && get_class($exception) == 'Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException') {
+      $site_name = \Drupal::config('system.site')->get('name');
+      global $base_url;
+      $challenge = format_string('Basic realm="@realm"', array(
+        '@realm' => !empty($site_name) ? $site_name : $base_url,
+      ));
+      $event->setException(new UnauthorizedHttpException($challenge, 'No authentication credentials provided.', $exception));
+      return TRUE;
+    }
+    return FALSE;
+  }
+}
diff --git a/core/lib/Drupal/Core/Controller/ExceptionController.php b/core/lib/Drupal/Core/Controller/ExceptionController.php
index c9a661b..9e7d77e 100644
--- a/core/lib/Drupal/Core/Controller/ExceptionController.php
+++ b/core/lib/Drupal/Core/Controller/ExceptionController.php
@@ -42,12 +42,12 @@ public function __construct(ContentNegotiation $negotiation) {
   /**
    * Handles an exception on a request.
    *
-   * @param Symfony\Component\HttpKernel\Exception\FlattenException $exception
+   * @param \Symfony\Component\HttpKernel\Exception\FlattenException $exception
    *   The flattened exception.
-   * @param Symfony\Component\HttpFoundation\Request $request
+   * @param \Symfony\Component\HttpFoundation\Request $request
    *   The request that generated the exception.
    *
-   * @return Symfony\Component\HttpFoundation\Response
+   * @return \Symfony\Component\HttpFoundation\Response
    *   A response object to be sent to the server.
    */
   public function execute(FlattenException $exception, Request $request) {
@@ -57,7 +57,7 @@ public function execute(FlattenException $exception, Request $request) {
       return $this->$method($exception, $request);
     }
 
-    return new Response('A fatal error occurred: ' . $exception->getMessage(), $exception->getStatusCode());
+    return new Response('A fatal error occurred: ' . $exception->getMessage(), $exception->getStatusCode(), $exception->getHeaders());
   }
 
   /**
diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php
index 9af0c74..b5aaa93 100644
--- a/core/lib/Drupal/Core/CoreBundle.php
+++ b/core/lib/Drupal/Core/CoreBundle.php
@@ -18,6 +18,7 @@
 use Drupal\Core\DependencyInjection\Compiler\RegisterServicesForDestructionPass;
 use Drupal\Core\DependencyInjection\Compiler\RegisterStringTranslatorsPass;
 use Drupal\Core\DependencyInjection\Compiler\RegisterBreadcrumbBuilderPass;
+use Drupal\Core\DependencyInjection\Compiler\RegisterAuthenticationPass;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Reference;
@@ -67,6 +68,8 @@ public function build(ContainerBuilder $container) {
     // Add the compiler pass that will process the tagged breadcrumb builder
     // services.
     $container->addCompilerPass(new RegisterBreadcrumbBuilderPass());
+    // Add the compiler pass that will process tagged authentication services.
+    $container->addCompilerPass(new RegisterAuthenticationPass());
   }
 
   /**
diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterAuthenticationPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterAuthenticationPass.php
new file mode 100644
index 0000000..c66a03a
--- /dev/null
+++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterAuthenticationPass.php
@@ -0,0 +1,44 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\DependencyInjection\Compiler\RegisterAuthenticationPass.
+ */
+
+namespace Drupal\Core\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+
+/**
+ * Adds services tagged 'authentication_provider'.
+ */
+class RegisterAuthenticationPass implements CompilerPassInterface {
+
+  /**
+   * Adds authentication providers to the authentication manager.
+   *
+   * Check for services tagged with 'authentication_provider' and add them to
+   * the authentication manager.
+   *
+   * @see Drupal\Core\Authentication\AuthenticationManager
+   * @see Drupal\Core\Authentication\AuthenticationProviderInterface
+   */
+  public function process(ContainerBuilder $container) {
+    if (!$container->hasDefinition('authentication')) {
+      return;
+    }
+    // Get the authentication manager.
+    $matcher = $container->getDefinition('authentication');
+    // Iterate all autentication providers and add them to the manager.
+    foreach ($container->findTaggedServiceIds('authentication_provider') as $id => $attributes) {
+      $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
+      $matcher->addMethodCall('addProvider', array(
+        $id,
+        new Reference($id),
+        $priority,
+      ));
+    }
+  }
+}
diff --git a/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php
new file mode 100644
index 0000000..030abe3
--- /dev/null
+++ b/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php
@@ -0,0 +1,94 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\EventSubscriber\AuthenticationSubscriber.
+ */
+
+namespace Drupal\Core\EventSubscriber;
+
+use Drupal\Core\Authentication\AuthenticationProviderInterface;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
+use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Authentication subscriber.
+ *
+ * Trigger authentication and cleanup during the request.
+ */
+class AuthenticationSubscriber implements EventSubscriberInterface {
+
+  /**
+   * Authentication manager.
+   *
+   * @var AuthenticationProviderInterface
+   */
+  protected $authenticationManager;
+
+  /**
+   * Keep authentication manager as private variable.
+   *
+   * @param AuthenticationProviderInterface $authentication_manager
+   *   The authentication manager.
+   */
+  public function __construct(AuthenticationProviderInterface $authentication_manager) {
+    $this->authenticationManager = $authentication_manager;
+  }
+
+  /**
+   * Authenticates user on request.
+   *
+   * @see Drupal\Core\Authentication\AuthenticationProviderInterface::authenticate()
+   */
+  public function onKernelRequestAuthenticate(GetResponseEvent $event) {
+    if ($event->getRequestType() == HttpKernelInterface::MASTER_REQUEST) {
+      $request = $event->getRequest();
+      $this->authenticationManager->authenticate($request);
+    }
+  }
+
+  /**
+   * Triggers authentication clean up on response.
+   *
+   * @see Drupal\Core\Authentication\AuthenticationProviderInterface::cleanup()
+   */
+  public function onRespond(FilterResponseEvent $event) {
+    if ($event->getRequestType() == HttpKernelInterface::MASTER_REQUEST) {
+      $request = $event->getRequest();
+
+      $this->authenticationManager->cleanup($request);
+    }
+  }
+
+  /**
+   * Pass exception handling to authentication manager.
+   *
+   * @param GetResponseForExceptionEvent $event
+   */
+  public function onException(GetResponseForExceptionEvent $event) {
+    if ($event->getRequestType() == HttpKernelInterface::MASTER_REQUEST) {
+      $this->authenticationManager->handleException($event);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * The priority for request must be higher than the highest event subscriber
+   * accessing the global $user.
+   * The priority for the response must be as low as possible allowing e.g the
+   * Cookie provider to send all relevant session data to the user.
+   */
+  public static function getSubscribedEvents() {
+    // Priority must be higher than LanguageRequestSubscriber as LanguageManager
+    // access global $user in case language module enabled.
+    $events[KernelEvents::REQUEST][] = array('onKernelRequestAuthenticate', 300);
+    $events[KernelEvents::RESPONSE][] = array('onRespond', 0);
+    $events[KernelEvents::EXCEPTION][] = array('onException', 0);
+    return $events;
+  }
+}
diff --git a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
index 0b9bbad..98eef05 100644
--- a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
@@ -91,8 +91,6 @@ public function onRespond(FilterResponseEvent $event) {
     // @todo Revisit whether or not this is still appropriate now that the
     //   Response object does its own cache control processing and we intend to
     //   use partial page caching more extensively.
-    // Commit the user session, if needed.
-    drupal_session_commit();
 
     // Attach globally-declared headers to the response object so that Symfony
     // can send them for us correctly.
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
index d3ba7b3..975788a 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -876,6 +876,7 @@ protected function prepareEnvironment() {
     $this->originalUser = isset($user) ? clone $user : NULL;
 
     // Ensure that the current session is not changed by the new environment.
+    require_once DRUPAL_ROOT . '/' . settings()->get('session_inc', 'core/includes/session.inc');
     drupal_save_session(FALSE);
     // Run all tests as a anonymous user by default, web tests will replace that
     // during the test set up.
diff --git a/core/modules/system/lib/Drupal/system/Tests/Authentication/HttpBasicTest.php b/core/modules/system/lib/Drupal/system/Tests/Authentication/HttpBasicTest.php
new file mode 100644
index 0000000..948c525
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Authentication/HttpBasicTest.php
@@ -0,0 +1,86 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\system\Tests\Authentication\HttpBasicTest.
+ */
+
+namespace Drupal\system\Tests\Authentication;
+
+use Drupal\Core\Authentication\Provider\HttpBasic;
+use Drupal\simpletest\WebTestBase;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Test for http basic authentication.
+ */
+class HttpBasicTest extends WebTestBase {
+
+  /**
+   * Modules enabled for all tests.
+   *
+   * @var array
+   */
+  public static $modules = array('router_test');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'HttpBasic authentication',
+      'description' => 'Tests for HttpBasic authentication provider.',
+      'group' => 'Authentication',
+    );
+  }
+
+  /**
+   * Test http basic authentication.
+   */
+  public function testHttpBasic() {
+    $account = $this->drupalCreateUser();
+
+    $this->basicAuthGet('router_test/test11', $account->name, $account->pass_raw);
+    $this->assertText($account->name, 'Account name is displayed.');
+    $this->assertResponse('200', 'HTTP response is OK');
+    $this->curlClose();
+
+    $this->basicAuthGet('router_test/test11', $account->name, $this->randomName());
+    $this->assertNoText($account->name, 'Bad basic auth credentials do not authenticate the user.');
+    $this->assertResponse('200', 'HTTP response is OK');
+    $this->curlClose();
+
+    $this->drupalGet('router_test/test11');
+    $this->assertResponse('401', 'Not authenticated on the route that allows only http_basic. Prompt to authenticate received.');
+  }
+
+  /**
+   * Dos HTTP basic auth request.
+   *
+   * We do not use drupalGet because we need to set curl settings for basic
+   * authentication.
+   *
+   * @param string $path
+   *   The request path.
+   * @param string $username
+   *   The user name to authenticate with.
+   * @param string $password
+   *   The password.
+   *
+   * @return string
+   *   Curl output.
+   */
+  protected function basicAuthGet($path, $username, $password) {
+    $out = $this->curlExec(
+      array(
+        CURLOPT_HTTPGET => TRUE,
+        CURLOPT_URL => url($path, array('absolute' => TRUE)),
+        CURLOPT_NOBODY => FALSE,
+        CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
+        CURLOPT_USERPWD => $username . ':' . $password,
+      )
+    );
+
+    $this->verbose('GET request to: ' . $path .
+      '<hr />' . $out);
+
+    return $out;
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php
index b613121..9de96b0 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php
@@ -93,6 +93,10 @@ protected function setUp() {
     // Load the Update API.
     require_once DRUPAL_ROOT . '/core/includes/update.inc';
 
+    // Load Session API.
+    require_once DRUPAL_ROOT . '/core/includes/session.inc';
+    drupal_session_initialize();
+
     // Reset flags.
     $this->upgradedSite = FALSE;
     $this->upgradeErrors = array();
diff --git a/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/TestContent.php b/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/TestContent.php
index 56d567b..22a07cf 100644
--- a/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/TestContent.php
+++ b/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/TestContent.php
@@ -19,4 +19,15 @@ public function test1() {
     return 'abcde';
   }
 
+  /**
+   * Provides example content for route specific authentication.
+   *
+   * @returns string
+   *   The user name of the current logged in user.
+   */
+  public function test11() {
+    global $user;
+    return isset($user->name) ? $user->name : '';
+  }
+
 }
diff --git a/core/modules/system/tests/modules/router_test/router_test.routing.yml b/core/modules/system/tests/modules/router_test/router_test.routing.yml
index 2a989df..9e481de 100644
--- a/core/modules/system/tests/modules/router_test/router_test.routing.yml
+++ b/core/modules/system/tests/modules/router_test/router_test.routing.yml
@@ -60,3 +60,10 @@ router_test_10:
     _content: '\Drupal\router_test\TestContent::test1'
   requirements:
     _access: 'TRUE'
+
+router_test_11:
+  pattern: '/router_test/test11'
+  options:
+    _auth: [ 'http_basic' ]
+  defaults:
+    _content: '\Drupal\router_test\TestContent::test11'
diff --git a/core/modules/system/tests/modules/session_test/lib/Drupal/session_test/EventSubscriber/SessionTestSubscriber.php b/core/modules/system/tests/modules/session_test/lib/Drupal/session_test/EventSubscriber/SessionTestSubscriber.php
index 45234a8..44e2882 100644
--- a/core/modules/system/tests/modules/session_test/lib/Drupal/session_test/EventSubscriber/SessionTestSubscriber.php
+++ b/core/modules/system/tests/modules/session_test/lib/Drupal/session_test/EventSubscriber/SessionTestSubscriber.php
@@ -65,7 +65,7 @@ public function onKernelResponseSessionTest(FilterResponseEvent $event) {
    */
   static function getSubscribedEvents() {
     $events[KernelEvents::RESPONSE][] = array('onKernelResponseSessionTest', 300);
-    $events[KernelEvents::REQUEST][] = array('onKernelRequestSessionTest', 300);
+    $events[KernelEvents::REQUEST][] = array('onKernelRequestSessionTest', 100);
     return $events;
   }
 
diff --git a/core/update.php b/core/update.php
index b73e3ce..f97a973 100644
--- a/core/update.php
+++ b/core/update.php
@@ -427,7 +427,9 @@ function update_check_requirements($skip_warnings = FALSE) {
 update_prepare_d8_bootstrap();
 
 // Determine if the current user has access to run update.php.
-drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION);
+drupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES);
+require_once DRUPAL_ROOT . '/' . settings()->get('session_inc', 'core/includes/session.inc');
+drupal_session_initialize();
 
 // A request object from the HTTPFoundation to tell us about the request.
 // @todo These two lines were copied from index.php which has its own todo about
