diff --git a/core/lib/Drupal/Core/Access/AccessGroupAnd.php b/core/lib/Drupal/Core/Access/AccessGroupAnd.php
new file mode 100644
index 0000000000..64a66d7afb
--- /dev/null
+++ b/core/lib/Drupal/Core/Access/AccessGroupAnd.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace Drupal\Core\Access;
+
+/**
+ * An access group where all the dependencies must be allowed.
+ */
+class AccessGroupAnd extends AccessibleGroupBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function doCombineAccess(AccessResultInterface $accumulatedAccess, AccessResultInterface $dependencyAccess) {
+    return $accumulatedAccess->andIf($dependencyAccess);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Access/AccessGroupOr.php b/core/lib/Drupal/Core/Access/AccessGroupOr.php
new file mode 100644
index 0000000000..7389f2d318
--- /dev/null
+++ b/core/lib/Drupal/Core/Access/AccessGroupOr.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Drupal\Core\Access;
+
+
+/**
+ * An access group where at least one dependencies must be allowed.
+ */
+class AccessGroupOr extends AccessibleGroupBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function doCombineAccess(AccessResultInterface $accumulatedAccess, AccessResultInterface $dependencyAccess) {
+    return $accumulatedAccess->orIf($dependencyAccess);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Access/AccessibleGroupBase.php b/core/lib/Drupal/Core/Access/AccessibleGroupBase.php
new file mode 100644
index 0000000000..876df62215
--- /dev/null
+++ b/core/lib/Drupal/Core/Access/AccessibleGroupBase.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace Drupal\Core\Access;
+
+use Drupal\Core\Session\AccountInterface;
+
+/**
+ * A base class for accessible groups classes.
+ */
+abstract class AccessibleGroupBase implements AccessibleGroupInterface {
+
+  /**
+   * The access dependencies.
+   *
+   * @var \Drupal\Core\Access\AccessibleInterface[]
+   */
+  protected $dependencies = [];
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addDependency(AccessibleInterface $dependency) {
+    $this->dependencies[] = $dependency;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function access($operation, AccountInterface $account = NULL, $return_as_object = FALSE) {
+    $access_result = NULL;
+    foreach ($this->dependencies as $dependency) {
+      $dependency_access_result = $dependency->access($operation, $account, TRUE);
+      if ($access_result === NULL) {
+        $access_result = $dependency_access_result;
+      }
+      else {
+        $access_result = $this->doCombineAccess($access_result, $dependency_access_result);
+      }
+    }
+    return $return_as_object ? $access_result : $access_result->isAllowed();
+  }
+
+  /**
+   * Combines the access result of one dependency to previous dependencies.
+   *
+   * @param \Drupal\Core\Access\AccessResultInterface $accumulatedAccess
+   *   The combine access result of previous dependencies.
+   * @param \Drupal\Core\Access\AccessResultInterface $dependencyAccess
+   *   The access result of the current dependency.
+   *
+   * @return \Drupal\Core\Access\AccessResultInterface
+   *   The combined access result.
+   */
+  abstract protected function doCombineAccess(AccessResultInterface $accumulatedAccess, AccessResultInterface $dependencyAccess);
+
+}
diff --git a/core/lib/Drupal/Core/Access/AccessibleGroupInterface.php b/core/lib/Drupal/Core/Access/AccessibleGroupInterface.php
new file mode 100644
index 0000000000..1c460074c0
--- /dev/null
+++ b/core/lib/Drupal/Core/Access/AccessibleGroupInterface.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace Drupal\Core\Access;
+
+/**
+ * Extends AccessibleInterface to allow for access objects that have multiple
+ * dependencies.
+ */
+interface AccessibleGroupInterface extends AccessibleInterface {
+
+  /**
+   * Adds an access dependency.
+   *
+   * @param \Drupal\Core\Access\AccessibleInterface $dependency
+   *   The access dependency.
+   *
+   * @return $this
+   */
+  public function addDependency(AccessibleInterface $dependency);
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Access/AccessGroupTest.php b/core/tests/Drupal/Tests/Core/Access/AccessGroupTest.php
new file mode 100644
index 0000000000..e4f92e0474
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Access/AccessGroupTest.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace Drupal\Tests\Core\Access;
+
+use Drupal\Core\Access\AccessGroupAnd;
+use Drupal\Core\Access\AccessGroupOr;
+use Drupal\Core\Access\AccessibleInterface;
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Access\AccessResultInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\Tests\UnitTestCase;
+
+class AccessGroupTest extends UnitTestCase {
+
+  /**
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $account;
+
+  protected function setUp() {
+    parent::setUp(); // TODO: Change the autogenerated stub
+    $this->account = $this->prophesize(AccountInterface::class)->reveal();
+  }
+
+
+  public function testGroups() {
+    $allowedAccessible = $this->makeAccessbileProh(AccessResult::allowed());
+    $forbiddenAccessible = $this->makeAccessbileProh(AccessResult::forbidden());
+    $neutralAccessible = $this->makeAccessbileProh(AccessResult::neutral());
+
+
+
+    $orForbidden = new AccessGroupOr();
+    $orForbidden->addDependency($allowedAccessible)->addDependency($forbiddenAccessible);
+    $this->assertTrue($orForbidden->access('view', $this->account, TRUE)->isForbidden());
+
+    $orAllowed = new AccessGroupOr();
+    $orAllowed->addDependency($allowedAccessible)->addDependency($neutralAccessible);
+    $this->assertTrue($orAllowed->access('view', $this->account, TRUE)->isAllowed());
+
+    $andNeutral = new AccessGroupAnd();
+    $andNeutral->addDependency($allowedAccessible)->addDependency($neutralAccessible);
+    $this->assertTrue($andNeutral->access('view', $this->account, TRUE)->isNeutral());
+
+    // We can also add groups and dependencies!!!!! Nested!!!!!
+    $andNeutral->addDependency($orAllowed);
+    $this->assertTrue($andNeutral->access('view', $this->account, TRUE)->isNeutral());
+
+    $andForbidden = $andNeutral;
+    $andForbidden->addDependency($forbiddenAccessible);
+    $this->assertTrue($andForbidden->access('view', $this->account, TRUE)->isForbidden());
+
+    // We can make groups from other groups!
+    $andGroupsForbidden = new AccessGroupAnd();
+    $andGroupsForbidden->addDependency($andNeutral)->addDependency($andForbidden)->addDependency($orForbidden);
+    $this->assertTrue($andGroupsForbidden->access('view', $this->account, TRUE)->isForbidden());
+    // But then would could also add a non-group accessible.
+    $andGroupsForbidden->addDependency($allowedAccessible);
+    $this->assertTrue($andGroupsForbidden->access('view', $this->account, TRUE)->isForbidden());
+
+  }
+
+  /**
+   * @param \Drupal\Core\Access\AccessResultInterface $accessResult
+   *
+   * @return AccessibleInterface
+   */
+  private function makeAccessbileProh(AccessResultInterface $accessResult) {
+    $accessible = $this->prophesize(AccessibleInterface::class);
+    $accessible->access('view', $this->account, TRUE)
+      ->willReturn($accessResult);
+    return $accessible->reveal();
+  }
+
+}
