diff --git a/core/includes/install.inc b/core/includes/install.inc
index 4a2b41b..1cedb63 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -5,6 +5,7 @@
  * API functions for installing modules and themes.
  */
 
+use Composer\Semver\Semver;
 use Drupal\Component\Utility\Unicode;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Drupal\Component\Utility\Crypt;
@@ -963,7 +964,8 @@ function drupal_requirements_severity(&$requirements) {
 function drupal_check_module($module) {
   module_load_install($module);
   // Check requirements
-  $requirements = \Drupal::moduleHandler()->invoke($module, 'requirements', array('install'));
+  $requirements = \Drupal::moduleHandler()->invoke($module, 'requirements', array('install')) ?: [];
+  $requirements += drupal_check_composer_requirements($module);
   if (is_array($requirements) && drupal_requirements_severity($requirements) == REQUIREMENT_ERROR) {
     // Print any error messages
     foreach ($requirements as $requirement) {
@@ -981,6 +983,88 @@ function drupal_check_module($module) {
 }
 
 /**
+ * Check composer requirements.
+ *
+ * @param string $module
+ *   Module name.
+ * @return array
+ */
+function drupal_check_composer_requirements($module) {
+  $module_dir = drupal_get_path('module', $module);
+
+  // Check if the modules that are going to be installed have a composer.json
+  // file, if they have one, make sure that the configured dependencies are
+  // installed. If failures are detected, make sure the dependent modules
+  // aren't installed either.
+  if (file_exists($module_dir . '/composer.json')) {
+
+    $semver = new Semver();
+
+    $module_composer_json = json_decode(file_get_contents($module_dir . '/composer.json'));
+    $module_package_requirements = $module_composer_json->require;
+
+    // Load the actual autoloader being used and determine its filename using
+    // reflection. We can determine the vendor directory based on that filename.
+    $autoloader = require \Drupal::root() . '/autoload.php';
+    $reflector = new ReflectionClass($autoloader);
+    $vendor_dir = dirname(dirname($reflector->getFileName()));
+
+    // The json in composer/installed.json includes all the installed packages
+    // and is more reliable than checking composer.lock, vendors actually have
+    // to be installed for this file to even be available.
+    if (file_exists($vendor_dir . '/composer/installed.json')) {
+      $installed_packages = json_decode(file_get_contents($vendor_dir.'/composer/installed.json'));
+    }
+    else {
+      $installed_packages = [];
+      $requirements['composer_dependencies'] = [
+        'description' => t('Not all the modules have their Composer dependencies installed yet. Please find more information on <a href="@handbook">this handbook page</a>.',
+          [
+            '@handbook' => 'https://www.drupal.org/node/2494073'
+          ]),
+        'severity' => REQUIREMENT_ERROR,
+        'title' => $module,
+      ];
+    }
+
+    $check_installed_packages = [];
+    $required_packages = [];
+
+    foreach ($module_package_requirements as $name => $version) {
+      foreach ($installed_packages as $package) {
+        if ($package->name === $name && $semver->satisfies($package->version_normalized, $version)) {
+          $check_installed_packages[] = $name;
+        }
+      }
+      $required_packages[] = $name;
+    }
+
+    if ($required_packages !== $check_installed_packages) {
+      $requirements['composer_dependencies'] = [
+        'description' => t('Not all the modules have their Composer dependencies installed yet. Please find more information on <a href="@handbook">this handbook page</a>.',
+          [
+            '@handbook' => 'https://www.drupal.org/node/2494073'
+          ]),
+        'severity' => REQUIREMENT_ERROR,
+        'title' => $module,
+      ];
+    }
+    else {
+      $requirements['composer_dependencies'] = [
+        'description' => t('All Composer dependencies have been installed.'),
+        'severity' => REQUIREMENT_OK,
+        'value' => t('Never run'),
+        'title' => $module,
+      ];
+    }
+
+    return $requirements;
+  }
+
+  return [];
+}
+
+/**
  * Retrieves information about an installation profile from its .info.yml file.
  *
  * The information stored in a profile .info.yml file is similar to that stored
diff --git a/core/lib/Drupal/Core/Extension/ExtensionComposerRequirementsException.php b/core/lib/Drupal/Core/Extension/ExtensionComposerRequirementsException.php
new file mode 100644
index 0000000..7256bbf
--- /dev/null
+++ b/core/lib/Drupal/Core/Extension/ExtensionComposerRequirementsException.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Extension\ExtensionComposerRequirementsException.
+ */
+
+namespace Drupal\Core\Extension;
+
+/**
+ * Exception thrown when the extension's composer requirements are not installed.
+ */
+class ExtensionComposerRequirementsException extends \Exception { }
diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
index 92bdb80..37fdde6 100644
--- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php
+++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
@@ -141,6 +141,11 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
           throw new ExtensionNameLengthException("Module name '$module' is over the maximum allowed length of " . DRUPAL_EXTENSION_NAME_MAX_LENGTH . ' characters');
         }
 
+        $composer_requirements = drupal_check_composer_requirements($module);
+        if (isset($composer_requirements['composer_dependencies']) && $composer_requirements['composer_dependencies']['severity'] == REQUIREMENT_ERROR) {
+          throw new ExtensionComposerRequirementsException("Module '$module' composer requirements are not installed yet.");
+        }
+
         // Check the validity of the default configuration. This will throw
         // exceptions if the configuration is not valid.
         $config_installer->checkConfigurationToInstall('module', $module);
diff --git a/core/modules/system/src/Tests/Module/HookRequirementsTest.php b/core/modules/system/src/Tests/Module/HookRequirementsTest.php
index 83fdce9..482d05b 100644
--- a/core/modules/system/src/Tests/Module/HookRequirementsTest.php
+++ b/core/modules/system/src/Tests/Module/HookRequirementsTest.php
@@ -28,4 +28,34 @@ function testHookRequirementsFailure() {
     $this->assertText(t('Requirements 1 Test failed requirements'), 'Modules status has been updated.');
     $this->assertModules(array('requirements1_test'), FALSE);
   }
+
+  /**
+   * A module with uninstalled Composer dependencies is not installable.
+   */
+  function testComposerDependenciesFailure() {
+    $this->assertModules(['composer_uninstallable'], FALSE);
+
+    // Attempt to install the composer_uninstallable module.
+    $edit = [];
+    $edit['modules[Testing][composer_uninstallable][enable]'] = 'composer_uninstallable';
+    $this->drupalPostForm('admin/modules', $edit, t('Install'));
+
+    // Makes sure the module was NOT installed.
+    $this->assertModules(['composer_uninstallable'], FALSE);
+  }
+
+  /**
+   * A module with installed Composer dependencies is installable.
+   */
+  function testComposerDependenciesSuccess() {
+    $this->assertModules(['composer_installable'], FALSE);
+
+    // Attempt to install the composer_installable module.
+    $edit = [];
+    $edit['modules[Testing][composer_installable][enable]'] = 'composer_uninstallable';
+    $this->drupalPostForm('admin/modules', $edit, t('Install'));
+
+    // Makes sure the module was installed.
+    $this->assertModules(['composer_installable'], TRUE);
+  }
 }
diff --git a/core/modules/system/tests/modules/composer_installable/composer.json b/core/modules/system/tests/modules/composer_installable/composer.json
new file mode 100644
index 0000000..04a5827
--- /dev/null
+++ b/core/modules/system/tests/modules/composer_installable/composer.json
@@ -0,0 +1,6 @@
+{
+  "name": "drupal_test/composer_installable",
+  "require": {
+    "psr/log": "~1.0"
+  }
+}
diff --git a/core/modules/system/tests/modules/composer_installable/composer_installable.info.yml b/core/modules/system/tests/modules/composer_installable/composer_installable.info.yml
new file mode 100644
index 0000000..399e267
--- /dev/null
+++ b/core/modules/system/tests/modules/composer_installable/composer_installable.info.yml
@@ -0,0 +1,6 @@
+name: 'Composer Installable'
+type: module
+description: 'Test module that is installable because its composer dependencies have already been installed'
+package: Testing
+version: VERSION
+core: 8.x
diff --git a/core/modules/system/tests/modules/composer_uninstallable/composer.json b/core/modules/system/tests/modules/composer_uninstallable/composer.json
new file mode 100644
index 0000000..be1a94a
--- /dev/null
+++ b/core/modules/system/tests/modules/composer_uninstallable/composer.json
@@ -0,0 +1,6 @@
+{
+  "name": "drupal_test/composer_uninstallable",
+  "require": {
+    "scalopus/empty": "^1.1"
+  }
+}
diff --git a/core/modules/system/tests/modules/composer_uninstallable/composer_uninstallable.info.yml b/core/modules/system/tests/modules/composer_uninstallable/composer_uninstallable.info.yml
new file mode 100644
index 0000000..a7f734e
--- /dev/null
+++ b/core/modules/system/tests/modules/composer_uninstallable/composer_uninstallable.info.yml
@@ -0,0 +1,6 @@
+name: 'Composer Uninstallable'
+type: module
+description: 'Test module that is not installable because of missing composer dependencies.'
+package: Testing
+version: VERSION
+core: 8.x
