diff --git a/core/lib/Drupal/Core/Action/ActionManager.php b/core/lib/Drupal/Core/Action/ActionManager.php
index d3a4c0a..9e5e4d9 100644
--- a/core/lib/Drupal/Core/Action/ActionManager.php
+++ b/core/lib/Drupal/Core/Action/ActionManager.php
@@ -36,6 +36,8 @@ public function __construct(\Traversable $namespaces, CacheBackendInterface $cac
     parent::__construct('Plugin/Action', $namespaces, $module_handler, 'Drupal\Core\Annotation\Action');
     $this->alterInfo('action_info');
     $this->setCacheBackend($cache_backend, 'action_info');
+
+    $this->interface = '\Drupal\Core\Action\ActionInterface';
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
index e1d0731..c3c7121 100644
--- a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
+++ b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
@@ -9,7 +9,9 @@
 
 use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface;
 use Drupal\Component\Plugin\Discovery\DiscoveryCachedTrait;
+use Drupal\Component\Plugin\Exception\PluginException;
 use Drupal\Component\Plugin\Exception\PluginNotFoundException;
+use Drupal\Component\Utility\String;
 use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator;
 use Drupal\Component\Plugin\PluginManagerBase;
 use Drupal\Component\Plugin\PluginManagerInterface;
@@ -83,6 +85,13 @@ class DefaultPluginManager extends PluginManagerBase implements PluginManagerInt
   protected $defaults = array();
 
   /**
+   * Defines an interface each plugin should implement.
+   *
+   * @var string
+   */
+  protected $interface;
+
+  /**
    * Creates the discovery object.
    *
    * @param string|bool $subdir
@@ -237,6 +246,16 @@ protected function findDefinitions() {
       if (isset($plugin_definition['provider']) && !in_array($plugin_definition['provider'], array('core', 'component')) && !$this->moduleHandler->moduleExists($plugin_definition['provider'])) {
         unset($definitions[$plugin_id]);
       }
+      if (isset($this->interface)) {
+        $class = $plugin_definition['class'];
+        if (!is_subclass_of($class, $this->interface)) {
+          throw new PluginException(String::format('Plugin @plugin_id in @provider should implement interface @interface', array(
+            '@plugin_id' => $plugin_id,
+            '@provider' => $plugin_definition['provider'],
+            '@interface' => $this->interface,
+          )));
+        }
+      }
     }
     return $definitions;
   }
diff --git a/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Apple.php b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Apple.php
index 9aabeca..d81b6ba 100644
--- a/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Apple.php
+++ b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Apple.php
@@ -14,4 +14,4 @@
  *   color = "green"
  * )
  */
-class Apple {}
+class Apple implements FruitInterface {}
diff --git a/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Banana.php b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Banana.php
index 4801da5..5e4d180 100644
--- a/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Banana.php
+++ b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/Banana.php
@@ -17,6 +17,6 @@
  *   }
  * )
  */
-class Banana {
+class Banana implements FruitInterface {
 
 }
diff --git a/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/FruitInterface.php b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/FruitInterface.php
new file mode 100644
index 0000000..4c26071
--- /dev/null
+++ b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/fruit/FruitInterface.php
@@ -0,0 +1,14 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface.
+ */
+
+namespace Drupal\plugin_test\Plugin\plugin_test\fruit;
+
+/**
+ * Provides an interface for test plugins.
+ */
+interface FruitInterface { }
+
diff --git a/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php b/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php
index 7f7d3ac..c52b5cb 100644
--- a/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php
@@ -13,6 +13,8 @@
  * Tests the DefaultPluginManager.
  *
  * @group Plugin
+ *
+ * @coversDefaultClass \Drupal\Core\Plugin\DefaultPluginManager
  */
 class DefaultPluginManagerTest extends UnitTestCase {
 
@@ -207,6 +209,49 @@ public function testCacheClearWithTags() {
     $plugin_manager->clearCachedDefinitions();
   }
 
+  /**
+   * Tests plugins with the proper interface.
+   *
+   * @covers ::getDefinitions
+   */
+  public function testGetDefinitionsWithJustValidInterfaces() {
+    $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, NULL, NULL, '\Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface');
+
+    $definitions = $plugin_manager->getDefinitions();
+    $this->assertCount(2, $definitions);
+    $this->assertEquals($definitions, $this->expectedDefinitions);
+  }
+
+  /**
+   * Tests plugins without the proper interface.
+   *
+   * @covers ::getDefinitions
+   *
+   * @expectedException \Drupal\Component\Plugin\Exception\PluginException
+   * @expectedExceptionMessage Plugin cherry in plugin_test should implement interface \Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface
+   */
+  public function testGetDefinitionsWithInvalidInterfaces() {
+    $module_handler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
+
+    $module_handler->expects($this->any())
+      ->method('moduleExists')
+      ->with('plugin_test')
+      ->willReturn(FALSE);
+
+    $this->expectedDefinitions['cherry'] = array(
+      'id' => 'cherry',
+      'label' => 'Cherry',
+      'color' => 'red',
+      'class' => 'Drupal\plugin_test\Plugin\plugin_test\fruit\Cherry',
+      'provider' => 'plugin_test',
+    );
+    $this->expectedDefinitions['apple']['provider'] = 'plugin_test';
+    $this->expectedDefinitions['banana']['provider'] = 'plugin_test';
+
+    $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, $module_handler, NULL, '\Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface');
+    $plugin_manager->getDefinitions();
+  }
+
 }
 
 if (!defined('DRUPAL_ROOT')) {
diff --git a/core/tests/Drupal/Tests/Core/Plugin/TestPluginManager.php b/core/tests/Drupal/Tests/Core/Plugin/TestPluginManager.php
index a7ea79d..d6c6384 100644
--- a/core/tests/Drupal/Tests/Core/Plugin/TestPluginManager.php
+++ b/core/tests/Drupal/Tests/Core/Plugin/TestPluginManager.php
@@ -28,8 +28,10 @@ class TestPluginManager extends DefaultPluginManager {
    *   (optional) The module handler to invoke the alter hook with.
    * @param string $alter_hook
    *   (optional) Name of the alter hook.
+   * @param string $interface
+   *   (optional) The interface required for the plugins.
    */
-  public function __construct(\Traversable $namespaces, array $definitions, ModuleHandlerInterface $module_handler = NULL, $alter_hook = NULL) {
+  public function __construct(\Traversable $namespaces, array $definitions, ModuleHandlerInterface $module_handler = NULL, $alter_hook = NULL, $interface = NULL) {
     // Create the object that can be used to return definitions for all the
     // plugins available for this type. Most real plugin managers use a richer
     // discovery implementation, but StaticDiscovery lets us add some simple
@@ -46,6 +48,7 @@ public function __construct(\Traversable $namespaces, array $definitions, Module
     if ($alter_hook) {
       $this->alterInfo($alter_hook);
     }
+    $this->interface = $interface;
   }
 
 }
