diff --git a/core/modules/simpletest/tests/Drupal/simpletest/Tests/phpunit_error.xml b/core/modules/simpletest/tests/Drupal/simpletest/Tests/phpunit_error.xml
index a8cf4d9..95bde5d 100644
--- a/core/modules/simpletest/tests/Drupal/simpletest/Tests/phpunit_error.xml
+++ b/core/modules/simpletest/tests/Drupal/simpletest/Tests/phpunit_error.xml
@@ -17,22 +17,22 @@ Undefined index: foo
     </testsuite>
     <testsuite name="Drupal\Tests\Core\NestedArrayUnitTest" file="/home/chx/www/system/core/tests/Drupal/Tests/Core/NestedArrayUnitTest.php" namespace="Drupal\Tests\Core" fullPackage="Drupal.Tests.Core" tests="0" assertions="0" failures="0" errors="0" time="0.000000"/>
     <testsuite name="Drupal\breakpoint\Tests\BreakpointMediaQueryTest" file="/home/chx/www/system/core/modules/breakpoint/tests/Drupal/breakpoint/Tests/BreakpointMediaQueryTest.php" namespace="Drupal\breakpoint\Tests" fullPackage="Drupal.breakpoint.Tests" tests="0" assertions="0" failures="0" errors="0" time="0.000000"/>
-    <testsuite name="Drupal\Tests\Core\Route\RouterRoleTest" file="/var/www/d8/core/tests/Drupal/Tests/Core/Route/RouterRoleTest.php" namespace="Drupal\Tests\Core\Route" fullPackage="Drupal.Tests.Core.Route" tests="3" assertions="3" failures="3" errors="0" time="0.009176">
-      <testsuite name="Drupal\Tests\Core\Route\RouterRoleTest::testRoleAccess" tests="3" assertions="3" failures="3" errors="0" time="0.009176">
+    <testsuite name="Drupal\Tests\Core\Route\RoleAccessCheckTest" file="/var/www/d8/core/tests/Drupal/Tests/Core/Route/RoleAccessCheckTestkTest.php" namespace="Drupal\Tests\Core\Route" fullPackage="Drupal.Tests.Core.Route" tests="3" assertions="3" failures="3" errors="0" time="0.009176">
+      <testsuite name="Drupal\Tests\Core\Route\RoleAccessCheckTest::testRoleAccess" tests="3" assertions="3" failures="3" errors="0" time="0.009176">
         <testcase name="testRoleAccess with data set #0" assertions="1" time="0.004519">
-          <failure type="PHPUnit_Framework_ExpectationFailedException">Drupal\Tests\Core\Route\RouterRoleTest::testRoleAccess with data set #0 ('role_test_1', array(Drupal\user\Plugin\Core\Entity\User, Drupal\user\Plugin\Core\Entity\User))
+          <failure type="PHPUnit_Framework_ExpectationFailedException">Drupal\Tests\Core\Route\RoleAccessCheckTest::testRoleAccess with data set #0 ('role_test_1', array(Drupal\user\Plugin\Core\Entity\User, Drupal\user\Plugin\Core\Entity\User))
             Access granted for user with the roles role_test_1 on path: role_test_1
             Failed asserting that false is true.
           </failure>
         </testcase>
         <testcase name="testRoleAccess with data set #1" assertions="1" time="0.002354">
-          <failure type="PHPUnit_Framework_ExpectationFailedException">Drupal\Tests\Core\Route\RouterRoleTest::testRoleAccess with data set #1 ('role_test_2', array(Drupal\user\Plugin\Core\Entity\User, Drupal\user\Plugin\Core\Entity\User))
+          <failure type="PHPUnit_Framework_ExpectationFailedException">Drupal\Tests\Core\Route\RoleAccessCheckTest::testRoleAccess with data set #1 ('role_test_2', array(Drupal\user\Plugin\Core\Entity\User, Drupal\user\Plugin\Core\Entity\User))
             Access granted for user with the roles role_test_2 on path: role_test_2
             Failed asserting that false is true.
           </failure>
         </testcase>
         <testcase name="testRoleAccess with data set #2" assertions="1" time="0.002303">
-          <failure type="PHPUnit_Framework_ExpectationFailedException">Drupal\Tests\Core\Route\RouterRoleTest::testRoleAccess with data set #2 ('role_test_3', array(Drupal\user\Plugin\Core\Entity\User))
+          <failure type="PHPUnit_Framework_ExpectationFailedException">Drupal\Tests\Core\Route\RoleAccessCheckTest::testRoleAccess with data set #2 ('role_test_3', array(Drupal\user\Plugin\Core\Entity\User))
             Access granted for user with the roles role_test_1, role_test_2 on path: role_test_3
             Failed asserting that false is true.
           </failure>
diff --git a/core/modules/user/lib/Drupal/user/Access/RoleAccessCheck.php b/core/modules/user/lib/Drupal/user/Access/RoleAccessCheck.php
new file mode 100644
index 0000000..104763d
--- /dev/null
+++ b/core/modules/user/lib/Drupal/user/Access/RoleAccessCheck.php
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\user\Access\RoleAccessCheck.
+ */
+
+namespace Drupal\user\Access;
+
+use Drupal\Core\Access\AccessCheckInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Routing\Route;
+
+/**
+ * Determines access to routes based on roles.
+ *
+ * You can specify the '_role' key on route requirements. If you specify a
+ * single role, users with that role with have access. If you specify multiple
+ * ones you can conjunct them with AND by using a "+" and with OR by using ",".
+ */
+class RoleAccessCheck implements AccessCheckInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function applies(Route $route) {
+    return array_key_exists('_role', $route->getRequirements());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function access(Route $route, Request $request) {
+    // Requirements just allow strings, so this might be a comma separated list.
+    $rid_string = $route->getRequirement('_role');
+
+    // @todo Replace the role check with a correctly injected and session-using
+    //   alternative.
+    $account = $GLOBALS['user'];
+
+    $explode_and = array_filter(array_map('trim', explode('+', $rid_string)));
+    if (count($explode_and) > 1) {
+      $diff = array_diff($explode_and, array_keys($account->roles));
+      if (empty($diff)) {
+        return TRUE;
+      }
+    }
+    else {
+      $explode_or = array_filter(array_map('trim', explode(',', $rid_string)));
+      $intersection = array_intersect($explode_or, array_keys($account->roles));
+      if (!empty($intersection)) {
+        return TRUE;
+      }
+    }
+
+    // If there is no allowed role, return NULL to give other checks a chance.
+    return NULL;
+  }
+
+}
diff --git a/core/modules/user/user.services.yml b/core/modules/user/user.services.yml
index e8c5e52..77f93e2 100644
--- a/core/modules/user/user.services.yml
+++ b/core/modules/user/user.services.yml
@@ -7,6 +7,10 @@ services:
     class: Drupal\user\Access\RegisterAccessCheck
     tags:
       - { name: access_check }
+  access_check.user.role:
+    class: Drupal\user\Access\RoleAccessCheck
+    tags:
+      - { name: access_check }
   user.data:
     class: Drupal\user\UserData
     arguments: ['@database']
diff --git a/core/tests/Drupal/Tests/Core/Route/RoleAccessCheckTest.php b/core/tests/Drupal/Tests/Core/Route/RoleAccessCheckTest.php
new file mode 100644
index 0000000..2561c55
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Route/RoleAccessCheckTest.php
@@ -0,0 +1,157 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Route\RoleAccessCheckTest.
+ */
+
+namespace Drupal\Tests\Core\Route;
+
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Tests\UnitTestCase;
+use Drupal\user\Access\RoleAccessCheck;
+use Drupal\user\Plugin\Core\Entity\User;
+use Symfony\Component\DependencyInjection\Container;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\Routing\RouteCollection;
+
+// Needed because the Entity class uses this constant.
+// @todo Remove once http://drupal.org/node/1620010 is in.
+if (!defined('LANGUAGE_NOT_SPECIFIED')) {
+  define('LANGUAGE_NOT_SPECIFIED', 'und');
+}
+
+/**
+ * Defines tests for role based access in routes.
+ *
+ * @see \Drupal\user\Access\RoleAccessCheck
+ */
+class RoleAccessCheckTest extends UnitTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Router Role tests',
+      'description' => 'Test for the role based access checker in the routing system.',
+      'group' => 'Routing',
+    );
+  }
+
+  /**
+   * Generates the test route collection.
+   *
+   * @return \Symfony\Component\Routing\RouteCollection
+   *   Returns the test route collection.
+   */
+  protected function getTestRouteCollection() {
+    $route_collection = new RouteCollection();
+    $route_collection->add('role_test_1', new Route('/role_test_1',
+      array(
+        '_controller' => '\Drupal\router_test\TestControllers::test1',
+      ),
+      array(
+        '_role' => 'role_test_1',
+      )
+    ));
+    $route_collection->add('role_test_2', new Route('/role_test_2',
+      array(
+        '_controller' => '\Drupal\router_test\TestControllers::test1',
+      ),
+      array(
+        '_role' => 'role_test_2',
+      )
+    ));
+    $route_collection->add('role_test_3', new Route('/role_test_3',
+      array(
+        '_controller' => '\Drupal\router_test\TestControllers::test1',
+      ),
+      array(
+        '_role' => 'role_test_1+role_test_2',
+      )
+    ));
+    $route_collection->add('role_test_4', new Route('/role_test_4',
+      array(
+        '_controller' => '\Drupal\router_test\TestControllers::test1',
+      ),
+      array(
+        '_role' => 'role_test_1,role_test_2',
+      )
+    ));
+
+    return $route_collection;
+  }
+
+  /**
+   * Provides data for the role access test.
+   *
+   * @see \Drupal\Tests\Core\Route\RouterRoleTest::testRoleAccess
+   */
+  public function roleAccessProvider() {
+    // Setup two different roles used in the test.
+    $rid_1 = 'role_test_1';
+    $rid_2 = 'role_test_2';
+
+    // Setup one user with the first role, one with the second, one with both
+    // and one final without any of these two roles.
+    $account_1 = new User(array('uid' => 1), 'user');
+    $account_1->roles[$rid_1] = $rid_1;
+
+    $account_2 = new User(array('uid' => 2), 'user');
+    $account_2->roles[$rid_2] = $rid_2;
+
+    $account_12 = new User(array('uid' => 3), 'user');
+    $account_12->roles[$rid_1] = $rid_1;
+    $account_12->roles[$rid_2] = $rid_2;
+
+    $account_none = new User(array('uid' => 4), 'user');
+
+    // Setup expected values; specify which paths can be accessed by which user.
+    return array(
+      array('role_test_1', array($account_1, $account_12), array($account_2, $account_none)),
+      array('role_test_2', array($account_2, $account_12), array($account_1, $account_none)),
+      array('role_test_3', array($account_12), array($account_1, $account_2, $account_none)),
+      array('role_test_4', array($account_1, $account_2, $account_12), array()),
+    );
+  }
+
+  /**
+   * Tests role requirements on routes.
+   *
+   * @param string $path
+   *   The path to check access for.
+   * @param array $grant_accounts
+   *   A list of accounts which should have access to the given path.
+   * @param array $deny_accounts
+   *   A list of accounts which should not have access to the given path.
+   *
+   * @see \Drupal\Tests\Core\Route\RouterRoleTest::getTestRouteCollection
+   * @see \Drupal\Tests\Core\Route\RouterRoleTest::roleAccessProvider
+   *
+   * @dataProvider roleAccessProvider
+   */
+  public function testRoleAccess($path, $grant_accounts, $deny_accounts) {
+    $role_access_check = new RoleAccessCheck();
+    $collection = $this->getTestRouteCollection();
+
+    foreach ($grant_accounts as $account) {
+      // @todo Replace the global user with a properly injection session.
+      $GLOBALS['user'] = $account;
+
+      $subrequest = Request::create($path, 'GET');
+      $message = sprintf('Access granted for user with the roles %s on path: %s', implode(', ', $account->roles), $path);
+      $this->assertTrue($role_access_check->access($collection->get($path), $subrequest), $message);
+    }
+
+    // Check all users which don't have access.
+    foreach ($deny_accounts as $account) {
+      $GLOBALS['user'] = $account;
+
+      $subrequest = Request::create($path, 'GET');
+      $message = sprintf('Access denied for user %s with the roles %s on path: %s', $account->id(), implode(', ', $account->roles), $path);
+      $has_access = $role_access_check->access($collection->get($path), $subrequest);
+      $this->assertEmpty($has_access , $message);
+    }
+  }
+
+}
