diff --git a/core/core.services.yml b/core/core.services.yml
index e2939e9..fa7d8f9 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -1299,6 +1299,9 @@ services:
       - [setThemeManager, ['@theme.manager']]
   authentication:
     class: Drupal\Core\Authentication\AuthenticationManager
+    arguments: ['@authentication_collector']
+  authentication_collector:
+    class: Drupal\Core\Authentication\AuthenticationCollector
     tags:
       - { name: service_collector, tag: authentication_provider, call: addProvider }
   authentication_subscriber:
diff --git a/core/lib/Drupal/Core/Authentication/AuthenticationCollector.php b/core/lib/Drupal/Core/Authentication/AuthenticationCollector.php
new file mode 100644
index 0000000..60bd62c
--- /dev/null
+++ b/core/lib/Drupal/Core/Authentication/AuthenticationCollector.php
@@ -0,0 +1,89 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Authentication\AuthenticationCollector.
+ */
+
+namespace Drupal\Core\Authentication;
+
+/**
+ * A collector class for authentication providers.
+ */
+class AuthenticationCollector implements AuthenticationCollectorInterface {
+
+  /**
+   * Array of all registered authentication providers, keyed by ID.
+   *
+   * @var \Drupal\Core\Authentication\AuthenticationProviderInterface[]
+   */
+  protected $providers;
+
+  /**
+   * Array of all providers and their priority.
+   *
+   * @var array
+   */
+  protected $providerOrders = [];
+
+  /**
+   * Sorted list of registered providers.
+   *
+   * @var \Drupal\Core\Authentication\AuthenticationProviderInterface[]
+   */
+  protected $sortedProviders;
+
+  /**
+   * List of providers which are allowed on routes with no _auth option.
+   *
+   * @var string[]
+   */
+  protected $globalProviders;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addProvider(AuthenticationProviderInterface $provider, $provider_id, $priority = 0, $global = FALSE) {
+    $this->providers[$provider_id] = $provider;
+    $this->providerOrders[$priority][$provider_id] = $provider;
+    // Force the providers to be re-sorted.
+    $this->sortedProviders = NULL;
+
+    if ($global) {
+      $this->globalProviders[$provider_id] = TRUE;
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isGlobal($provider_id) {
+    return isset($this->globalProviders[$provider_id]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getProvider($provider_id) {
+    return isset($this->providers[$provider_id]) ? $this->providers[$provider_id] : NULL;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getSortedProviders() {
+    if (!isset($this->sortedProviders)) {
+      // Sort the providers according to priority.
+      krsort($this->providerOrders);
+
+      // Merge nested providers from $this->providers into $this->sortedProviders.
+      $this->sortedProviders = [];
+      foreach ($this->providerOrders as $providers) {
+        $this->sortedProviders = array_merge($this->sortedProviders, $providers);
+      }
+    }
+
+    return $this->sortedProviders;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Authentication/AuthenticationCollectorInterface.php b/core/lib/Drupal/Core/Authentication/AuthenticationCollectorInterface.php
new file mode 100644
index 0000000..5bf6a08
--- /dev/null
+++ b/core/lib/Drupal/Core/Authentication/AuthenticationCollectorInterface.php
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Authentication\AuthenticationCollectorInterface.
+ */
+
+namespace Drupal\Core\Authentication;
+
+/**
+ * Interface for collectors of registered authentication providers.
+ */
+interface AuthenticationCollectorInterface {
+
+  /**
+   * Adds a provider to the array of registered providers.
+   *
+   * @param \Drupal\Core\Authentication\AuthenticationProviderInterface $provider
+   *   The provider object.
+   * @param string $provider_id
+   *   Identifier of the provider.
+   * @param int $priority
+   *   (optional) The provider's priority.
+   * @param bool $global
+   *   (optional) TRUE if the provider is to be applied globally on all routes.
+   *   Defaults to FALSE.
+   */
+  public function addProvider(AuthenticationProviderInterface $provider, $provider_id, $priority = 0, $global = FALSE);
+
+  /**
+   * Returns whether a provider is considered global.
+   *
+   * @param string $provider_id
+   *   The provider ID.
+   *
+   * @return bool
+   *   TRUE if the provider is global, FALSE otherwise.
+   *
+   * @see \Drupal\Core\Authentication\AuthenticationCollectorInterface::addProvider
+   */
+  public function isGlobal($provider_id);
+
+  /**
+   * Returns an authentication provider.
+   *
+   * @param string $provider_id
+   *   The provider ID.
+   *
+   * @return \Drupal\Core\Authentication\AuthenticationProviderInterface|NULL
+   *   The authentication provider which matches the ID.
+   */
+  public function getProvider($provider_id);
+
+  /**
+   * Returns the sorted array of authentication providers.
+   *
+   * @return \Drupal\Core\Authentication\AuthenticationProviderInterface[]
+   *   An array of authentication provider objects.
+   */
+  public function getSortedProviders();
+
+}
diff --git a/core/lib/Drupal/Core/Authentication/AuthenticationManager.php b/core/lib/Drupal/Core/Authentication/AuthenticationManager.php
index ac50ae3..d95873d 100644
--- a/core/lib/Drupal/Core/Authentication/AuthenticationManager.php
+++ b/core/lib/Drupal/Core/Authentication/AuthenticationManager.php
@@ -20,69 +20,23 @@
  *
  * If no provider set an active user then the user is set to anonymous.
  */
-class AuthenticationManager implements AuthenticationProviderInterface, AuthenticationProviderFilterInterface, AuthenticationProviderChallengeInterface, AuthenticationManagerInterface {
+class AuthenticationManager implements AuthenticationProviderInterface, AuthenticationProviderFilterInterface, AuthenticationProviderChallengeInterface {
 
   /**
-   * Array of all registered authentication providers, keyed by ID.
+   * The authentication provider collector.
    *
-   * @var \Drupal\Core\Authentication\AuthenticationProviderInterface[]
+   * @var \Drupal\Core\Authentication\AuthenticationCollectorInterface
    */
-  protected $providers;
+  protected $authCollector;
 
   /**
-   * Array of all providers and their priority.
+   * Creates a new authentication manager instance.
    *
-   * @var array
+   * @param \Drupal\Core\Authentication\AuthenticationCollectorInterface $auth_collector
+   *   The authentication provider collector.
    */
-  protected $providerOrders = array();
-
-  /**
-   * Sorted list of registered providers.
-   *
-   * @var \Drupal\Core\Authentication\AuthenticationProviderInterface[]
-   */
-  protected $sortedProviders;
-
-  /**
-   * List of providers which implement the filter interface.
-   *
-   * @var \Drupal\Core\Authentication\AuthenticationProviderFilterInterface[]
-   */
-  protected $filters;
-
-  /**
-   * List of providers which implement the challenge interface.
-   *
-   * @var \Drupal\Core\Authentication\AuthenticationProviderChallengeInterface[]
-   */
-  protected $challengers;
-
-  /**
-   * List of providers which are allowed on routes with no _auth option.
-   *
-   * @var string[]
-   */
-  protected $globalProviders;
-
-  /**
-   * {@inheritdoc}
-   */
-  public function addProvider(AuthenticationProviderInterface $provider, $provider_id, $priority = 0, $global = FALSE) {
-    $this->providers[$provider_id] = $provider;
-    $this->providerOrders[$priority][$provider_id] = $provider;
-    // Force the builders to be re-sorted.
-    $this->sortedProviders = NULL;
-
-    if ($provider instanceof AuthenticationProviderFilterInterface) {
-      $this->filters[$provider_id] = $provider;
-    }
-    if ($provider instanceof AuthenticationProviderChallengeInterface) {
-      $this->challengers[$provider_id] = $provider;
-    }
-
-    if ($global) {
-      $this->globalProviders[$provider_id] = TRUE;
-    }
+  public function __construct(AuthenticationCollectorInterface $auth_collector) {
+    $this->authCollector = $auth_collector;
   }
 
   /**
@@ -97,7 +51,13 @@ public function applies(Request $request) {
    */
   public function authenticate(Request $request) {
     $provider_id = $this->getProvider($request);
-    return $this->providers[$provider_id]->authenticate($request);
+    $provider = $this->authCollector->getProvider($provider_id);
+
+    if ($provider) {
+      return $provider->authenticate($request);
+    }
+
+    return NULL;
   }
 
   /**
@@ -110,7 +70,7 @@ public function appliesToRoutedRequest(Request $request, $authenticated) {
       $result = $this->applyFilter($request, $authenticated, $this->getProvider($request));
     }
     else {
-      foreach ($this->getSortedProviders() as $provider_id => $provider) {
+      foreach ($this->authCollector->getSortedProviders() as $provider_id => $provider) {
         if ($this->applyFilter($request, $authenticated, $provider_id)) {
           $result = TRUE;
           break;
@@ -126,8 +86,10 @@ public function appliesToRoutedRequest(Request $request, $authenticated) {
    */
   public function challengeException(Request $request, \Exception $previous) {
     $provider_id = $this->getChallenger($request);
+
     if ($provider_id) {
-      return $this->challengers[$provider_id]->challengeException($request, $previous);
+      $provider = $this->authCollector->getProvider($provider_id);
+      return $provider->challengeException($request, $previous);
     }
   }
 
@@ -142,7 +104,7 @@ public function challengeException(Request $request, \Exception $previous) {
    *   If no application detects appropriate credentials, then NULL is returned.
    */
   protected function getProvider(Request $request) {
-    foreach ($this->getSortedProviders() as $provider_id => $provider) {
+    foreach ($this->authCollector->getSortedProviders() as $provider_id => $provider) {
       if ($provider->applies($request)) {
         return $provider_id;
       }
@@ -150,21 +112,19 @@ protected function getProvider(Request $request) {
   }
 
   /**
-   * Returns the id of the challenge provider for a request.
+   * Returns the ID of the challenge provider for a request.
    *
    * @param \Symfony\Component\HttpFoundation\Request $request
    *   The incoming request.
    *
    * @return string|NULL
-   *   The id of the first authentication provider which applies to the request.
+   *   The ID of the first authentication provider which applies to the request.
    *   If no application detects appropriate credentials, then NULL is returned.
    */
   protected function getChallenger(Request $request) {
-    if (!empty($this->challengers)) {
-      foreach ($this->getSortedProviders($request, FALSE) as $provider_id => $provider) {
-        if (isset($this->challengers[$provider_id]) && !$provider->applies($request) && $this->applyFilter($request, FALSE, $provider_id)) {
-          return $provider_id;
-        }
+    foreach ($this->authCollector->getSortedProviders() as $provider_id => $provider) {
+      if (($provider instanceof AuthenticationProviderChallengeInterface) && !$provider->applies($request) && $this->applyFilter($request, FALSE, $provider_id)) {
+        return $provider_id;
       }
     }
   }
@@ -186,8 +146,10 @@ protected function getChallenger(Request $request) {
    *   TRUE if provider is allowed, FALSE otherwise.
    */
   protected function applyFilter(Request $request, $authenticated, $provider_id) {
-    if (isset($this->filters[$provider_id])) {
-      $result = $this->filters[$provider_id]->appliesToRoutedRequest($request, $authenticated);
+    $provider = $this->authCollector->getProvider($provider_id);
+
+    if ($provider && ($provider instanceof AuthenticationProviderFilterInterface)) {
+      $result = $provider->appliesToRoutedRequest($request, $authenticated);
     }
     else {
       $result = $this->defaultFilter($request, $provider_id);
@@ -222,27 +184,8 @@ protected function defaultFilter(Request $request, $provider_id) {
       return in_array($provider_id, $route->getOption('_auth'));
     }
     else {
-      return isset($this->globalProviders[$provider_id]);
+      return $this->authCollector->isGlobal($provider_id);
     }
   }
 
-  /**
-   * Returns the sorted array of authentication providers.
-   *
-   * @return \Drupal\Core\Authentication\AuthenticationProviderInterface[]
-   *   An array of authentication provider objects.
-   */
-  protected function getSortedProviders() {
-    if (!isset($this->sortedProviders)) {
-      // Sort the builders according to priority.
-      krsort($this->providerOrders);
-      // Merge nested providers from $this->providers into $this->sortedProviders.
-      $this->sortedProviders = array();
-      foreach ($this->providerOrders as $providers) {
-        $this->sortedProviders = array_merge($this->sortedProviders, $providers);
-      }
-    }
-    return $this->sortedProviders;
-  }
-
 }
diff --git a/core/lib/Drupal/Core/Authentication/AuthenticationManagerInterface.php b/core/lib/Drupal/Core/Authentication/AuthenticationManagerInterface.php
deleted file mode 100644
index 2b8317b..0000000
--- a/core/lib/Drupal/Core/Authentication/AuthenticationManagerInterface.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Authentication\AuthenticationManagerInterface.
- */
-
-namespace Drupal\Core\Authentication;
-
-/**
- * Defines an interface for authentication managers.
- */
-interface AuthenticationManagerInterface {
-
-  /**
-   * Adds a provider to the array of registered providers.
-   *
-   * @param \Drupal\Core\Authentication\AuthenticationProviderInterface $provider
-   *   The provider object.
-   * @param string $provider_id
-   *   Identifier of the provider.
-   * @param int $priority
-   *   (optional) The provider's priority.
-   * @param bool $global
-   *   (optional) TRUE if the provider is to be applied globally on all routes.
-   *   Defaults to FALSE.
-   */
-  public function addProvider(AuthenticationProviderInterface $provider, $provider_id, $priority = 0, $global = FALSE);
-
-}
diff --git a/core/tests/Drupal/Tests/Core/Authentication/AuthenticationCollectorTest.php b/core/tests/Drupal/Tests/Core/Authentication/AuthenticationCollectorTest.php
new file mode 100644
index 0000000..609f4f3
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Authentication/AuthenticationCollectorTest.php
@@ -0,0 +1,95 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Authentication\AuthenticationCollectorTest.
+ */
+
+namespace Drupal\Tests\Core\Authentication;
+
+use Drupal\Core\Authentication\AuthenticationCollector;
+use Drupal\Core\Authentication\AuthenticationProviderInterface;
+use Drupal\Tests\UnitTestCase;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * @coversDefaultClass \Drupal\Core\Authentication\AuthenticationCollector
+ * @group Authentication
+ */
+class AuthenticationCollectorTest extends UnitTestCase {
+
+  /**
+   * Tests adding, getting, and order of priorities.
+   *
+   * @covers ::addProvider
+   * @covers ::getSortedProviders
+   * @covers ::getProvider
+   * @covers ::isGlobal
+   */
+  public function testAuthenticationCollector() {
+    $providers = [];
+    $global = [];
+    $authentication_collector = new AuthenticationCollector();
+    $priorities = [2, 0, -8, 10, 1, 3, -5, 0, 6, -10, -4];
+    foreach ($priorities as $priority) {
+      $provider_id = $this->randomMachineName();
+      $provider = new TestAuthenticationProvider($provider_id);
+      $providers[$priority][$provider_id] = $provider;
+      $global[$provider_id] = rand(0, 1) > 0.5;
+      $authentication_collector->addProvider($provider, $provider_id, $priority, $global[$provider_id]);
+    }
+    // Sort the $providers array by priority (highest number is lowest priority)
+    // and compare with AuthenticationCollector::getSortedProviders().
+    krsort($providers);
+
+    // Merge nested providers from $providers into $sorted_providers.
+    $sorted_providers = [];
+    foreach ($providers as $providers_priority) {
+      $sorted_providers = array_merge($sorted_providers, $providers_priority);
+    }
+    $this->assertEquals($sorted_providers, $authentication_collector->getSortedProviders());
+
+    // Test AuthenticationCollector::getProvider() and
+    // AuthenticationCollector::isGlobal().
+    foreach ($sorted_providers as $provider) {
+      $this->assertEquals($provider, $authentication_collector->getProvider($provider->providerId));
+      $this->assertEquals($global[$provider->providerId], $authentication_collector->isGlobal($provider->providerId));
+    }
+  }
+
+}
+
+/**
+ * A simple provider for unit testing AuthenticationCollector.
+ */
+class TestAuthenticationProvider implements AuthenticationProviderInterface {
+
+  /**
+   * The provider id.
+   *
+   * @var string
+   */
+  public $providerId;
+
+  /**
+   * Constructor.
+   */
+  public function __construct($provider_id) {
+    $this->providerId = $provider_id;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function applies(Request $request) {
+    return TRUE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function authenticate(Request $request) {
+    return NULL;
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Authentication/AuthenticationManagerTest.php b/core/tests/Drupal/Tests/Core/Authentication/AuthenticationManagerTest.php
index da7331d..315d5d6 100644
--- a/core/tests/Drupal/Tests/Core/Authentication/AuthenticationManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Authentication/AuthenticationManagerTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Tests\Core\Authentication;
 
+use Drupal\Core\Authentication\AuthenticationCollector;
 use Drupal\Core\Authentication\AuthenticationManager;
 use Drupal\Core\Authentication\AuthenticationProviderFilterInterface;
 use Drupal\Core\Authentication\AuthenticationProviderInterface;
@@ -28,9 +29,10 @@ class AuthenticationManagerTest extends UnitTestCase {
    * @dataProvider providerTestDefaultFilter
    */
   public function testDefaultFilter($applies, $has_route, $auth_option, $provider_id, $global) {
-    $authentication_manager = new AuthenticationManager();
     $auth_provider = $this->getMock('Drupal\Core\Authentication\AuthenticationProviderInterface');
-    $authentication_manager->addProvider($auth_provider, $provider_id, 0, $global);
+    $auth_collector = new AuthenticationCollector();
+    $auth_collector->addProvider($auth_provider, $provider_id, 0, $global);
+    $authentication_manager = new AuthenticationManager($auth_collector);
 
     $request = new Request();
     if ($has_route) {
@@ -48,14 +50,16 @@ public function testDefaultFilter($applies, $has_route, $auth_option, $provider_
    * @covers ::applyFilter
    */
   public function testApplyFilterWithFilterprovider() {
-    $authentication_manager = new AuthenticationManager();
     $auth_provider = $this->getMock('Drupal\Tests\Core\Authentication\TestAuthenticationProviderInterface');
-    $authentication_manager->addProvider($auth_provider, 'filtered', 0);
-
     $auth_provider->expects($this->once())
       ->method('appliesToRoutedRequest')
       ->willReturn(TRUE);
 
+    $authentication_collector = new AuthenticationCollector();
+    $authentication_collector->addProvider($auth_provider, 'filtered', 0);
+
+    $authentication_manager = new AuthenticationManager($authentication_collector);
+
     $request = new Request();
     $this->assertTrue($authentication_manager->appliesToRoutedRequest($request, FALSE));
   }
