diff --git a/core/modules/system/lib/Drupal/system/Tests/Routing/RouterRoleTest.php b/core/modules/system/lib/Drupal/system/Tests/Routing/RouterRoleTest.php
new file mode 100644
index 0000000..2f2f5ed
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Routing/RouterRoleTest.php
@@ -0,0 +1,102 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Tests\Routing\RouterRoleTest.
+ */
+
+namespace Drupal\system\Tests\Routing;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Defines tests for role based access in routes.
+ */
+class RouterRoleTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('router_test');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Router Role tests',
+      'description' => 'Function Tests for the routing role system.',
+      'group' => 'Routing',
+    );
+  }
+
+  /**
+   * Tests role requirements on routes.
+   */
+  public function testRoleAccess() {
+
+    // Setup two different roles used in the test.
+    $rid_1 = $this->drupalCreateRole(array(), 'role_test_1');
+    $rid_2 = $this->drupalCreateRole(array(), '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.
+    $all_uids = array();
+    $accounts = array();
+    $account_1 = $this->drupalCreateUser();
+    $account_1->roles[$rid_1] = $rid_1;
+    $account_1->save();
+    $all_uids[] = $account_1->id();
+    $accounts[$account_1->id()] = $account_1;
+
+    $account_2 = $this->drupalCreateUser();
+    $account_2->roles[$rid_2] = $rid_2;
+    $account_2->save();
+    $all_uids[] = $account_2->id();
+    $accounts[$account_2->id()] = $account_2;
+
+    $account_12 = $this->drupalCreateUser();
+    $account_12->roles[$rid_1] = $rid_1;
+    $account_12->roles[$rid_2] = $rid_2;
+    $account_12->save();
+    $all_uids[] = $account_12->id();
+    $accounts[$account_12->id()] = $account_12;
+
+    $account_none = $this->drupalCreateUser();
+    $all_uids[] = $account_none->id();
+    $accounts[$account_none->id()] = $account_none;
+
+    // Setup expected values, so which path can be access by which user.
+    $expected = array();
+    $expected['test10'] = array($account_1->id(), $account_12->id());
+    $expected['test11'] = array($account_2->id(), $account_12->id());
+    $expected['test12'] = array($account_12->id());
+    $expected['test13'] = array($account_1->id(), $account_2->id(), $account_12->id(), $account_none->id());
+
+    // @todo Decide whether it's worth to manipulate global $user; and directly
+    // check the access or call the actual pages.
+    foreach ($expected as $path => $uids) {
+      // Login for each user and check the access to the path.
+      foreach ($uids as $uid) {
+        $account = $accounts[$uid];
+        $this->drupalLogin($account);
+        $this->drupalGet('/router_test/' . $path);
+        $this->assertResponse(200, format_string('Access granted for user with the roles %roles on path: %path', array(
+          '%roles' => implode(', ', $account->roles),
+          '%path' => $path,
+        )));
+      }
+      // Check all users which don't have access.
+      foreach (array_diff($all_uids, $uids) as $uid) {
+        $account = $accounts[$uid];
+        $this->drupalLogin($account);
+        $this->drupalGet('/router_test/' . $path);
+        $this->assertResponse(403, format_string('Access denied for user with the roles %roles on path: %path', array(
+          '%roles' => implode(', ', $account->roles),
+          '%path' => $path,
+        )));
+      }
+    }
+
+  }
+
+}
diff --git a/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/TestControllers.php b/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/TestControllers.php
index adb5c34..2122909 100644
--- a/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/TestControllers.php
+++ b/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/TestControllers.php
@@ -46,4 +46,8 @@ public function test8() {
     return new Response('test8');
   }
 
+  public function testRole() {
+    return new Response('testRole');
+  }
+
 }
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 95b0cec..f78be38 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
@@ -53,3 +53,31 @@ router_test_9:
   requirements:
     _permission: 'access test7'
     _access_router_test: 'TRUE'
+
+router_test_10:
+  pattern: '/router_test/test10'
+  defaults:
+    _controller: '\Drupal\router_test\TestControllers::testRole'
+  requirements:
+    _role: 'role_test_1'
+
+router_test_11:
+  pattern: '/router_test/test11'
+  defaults:
+    _controller: '\Drupal\router_test\TestControllers::testRole'
+  requirements:
+    _role: 'role_test_2'
+
+router_test_12:
+  pattern: '/router_test/test12'
+  defaults:
+    _controller: '\Drupal\router_test\TestControllers::testRole'
+  requirements:
+      _role: 'role_test_1, role_test_2'
+
+router_test_13:
+  pattern: '/router_test/test13'
+  defaults:
+    _controller: '\Drupal\router_test\TestControllers::testRole'
+  requirements:
+    _access: 'TRUE'
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..9180dd2
--- /dev/null
+++ b/core/modules/user/lib/Drupal/user/Access/RoleAccessCheck.php
@@ -0,0 +1,47 @@
+<?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 defined via hook_permission().
+ */
+class RoleAccessCheck implements AccessCheckInterface {
+
+  /**
+   * Implements AccessCheckInterface::applies().
+   */
+  public function applies(Route $route) {
+    return array_key_exists('_role', $route->getRequirements());
+  }
+
+  /**
+   * Implements AccessCheckInterface::access().
+   */
+  public function access(Route $route, Request $request) {
+    // Requirements just allow strings, so this might be a comma separated list.
+    $rid_string = $route->getRequirement('_role');
+    $rids = array_map('trim', explode(',', $rid_string));
+    // @todo Replace the role check with a correctly injected and session-using
+    //   alternative.
+    $account = $GLOBALS['user'];
+    $roles = array_keys($account->roles);
+
+    $diff = array_diff(array_filter($rids), $roles);
+    if (empty($diff)) {
+      return TRUE;
+    }
+    else {
+      return NULL;
+    }
+  }
+
+}
diff --git a/core/modules/user/lib/Drupal/user/UserBundle.php b/core/modules/user/lib/Drupal/user/UserBundle.php
index f7c4a88..689a20c 100644
--- a/core/modules/user/lib/Drupal/user/UserBundle.php
+++ b/core/modules/user/lib/Drupal/user/UserBundle.php
@@ -24,6 +24,8 @@ public function build(ContainerBuilder $container) {
       ->addTag('access_check');
     $container->register('access_check.user.register', 'Drupal\user\Access\RegisterAccessCheck')
       ->addTag('access_check');
+    $container->register('access_check.user.role', 'Drupal\user\Access\RoleAccessCheck')
+      ->addTag('access_check');
     $container
       ->register('user.data', 'Drupal\user\UserData')
       ->addArgument(new Reference('database'));
