diff --git a/core/lib/Drupal/Core/Field/PluginSettingsInterface.php b/core/lib/Drupal/Core/Field/PluginSettingsInterface.php
index 9f9b7c6..41dd942 100644
--- a/core/lib/Drupal/Core/Field/PluginSettingsInterface.php
+++ b/core/lib/Drupal/Core/Field/PluginSettingsInterface.php
@@ -64,4 +64,55 @@ public function setSettings(array $settings);
    */
   public function setSetting($key, $value);
 
+  /**
+   * Returns the array of third-party settings.
+   *
+   * The array is keyed by the third-party module which provides the settings,
+   * and includes defaults for missing settings.
+   *
+   * @return mixed
+   *   The array of settings.
+   */
+  public function getThirdPartySettings();
+
+  /**
+   * Returns the value of a third-party setting, or its default value if absent.
+   *
+   * @param string $module
+   *   The module providing the third-party setting.
+   * @param string $key
+   *   The setting name.
+   *
+   * @return mixed
+   *   The setting value.
+   */
+  public function getThirdPartySetting($module, $key);
+
+  /**
+   * Sets the value of a third-party setting for the plugin.
+   *
+   * @param string $module
+   *   The module providing the third-party setting.
+   * @param string $key
+   *   The setting name.
+   * @param mixed $value
+   *   The setting value.
+   *
+   * @return $this
+   */
+  public function setThirdPartySetting($module, $key, $value);
+
+  /**
+   * Sets the third-party settings for the plugin.
+   *
+   * @param string $module
+   *   The module providing the third-party settings.
+   * @param array $settings
+   *   The array of settings provided by the module. Missing settings will be
+   *   assigned their default values.
+   *
+   * @return $this
+   */
+  public function setThirdPartySettings($module, array $settings);
+
 }
diff --git a/core/modules/entity/src/EntityDisplayBase.php b/core/modules/entity/src/EntityDisplayBase.php
index 07679f8..5170457 100644
--- a/core/modules/entity/src/EntityDisplayBase.php
+++ b/core/modules/entity/src/EntityDisplayBase.php
@@ -313,6 +313,12 @@ public function setComponent($name, array $options = array()) {
       $options = $this->pluginManager->prepareConfiguration($field_definition->getType(), $options);
     }
 
+    if (isset($options['third_party_settings'])) {
+      foreach (array_keys($options['third_party_settings']) as $module) {
+        $this->addDependency('module', $module);
+      }
+    }
+
     $this->content[$name] = $options;
     unset($this->hidden[$name]);
     unset($this->plugins[$name]);
diff --git a/core/modules/field/tests/modules/field_test/field_test.module b/core/modules/field/tests/modules/field_test/field_test.module
index 45a0c0d..8245815 100644
--- a/core/modules/field/tests/modules/field_test/field_test.module
+++ b/core/modules/field/tests/modules/field_test/field_test.module
@@ -156,14 +156,16 @@ function field_test_query_efq_metadata_test_alter(&$query) {
 }
 
 /**
- * Implements hook_field_widget_settings_form_alter().
+ * Implements hook_field_widget_third_party_settings_form().
  */
-function field_test_field_widget_settings_form_alter(&$element, &$form_state, $context) {
-  $element['field_test_widget_settings_form_alter'] = array(
+function field_test_field_widget_third_party_settings_form($plugin, \Drupal\Core\Field\FieldDefinitionInterface $field_definition, $form_mode, $form, $form_state) {
+  $third_party_settings = $plugin->getSetting('third_party_settings');
+  $element['field_test_widget_third_party_settings_form'] = array(
     '#type' => 'textfield',
-    '#title' => t('Widget settings form alter'),
-    '#default_value' => $context['widget']->getSetting('field_test_widget_settings_form_alter'),
+    '#title' => t('3rd party widget settings form'),
+    '#default_value' => $third_party_settings['field_test'],
   );
+  return $element;
 }
 
 /**
@@ -175,14 +177,16 @@ function field_test_field_widget_settings_summary_alter(&$summary, $context) {
 }
 
 /**
- * Implements hook_field_formatter_settings_form_alter().
+ * Implements hook_field_formatter_third_party_settings_form().
  */
-function field_test_field_formatter_settings_form_alter(&$element, &$form_state, $context) {
-  $element['field_test_formatter_settings_form_alter'] = array(
+function field_test_field_formatter_third_party_settings_form($plugin, \Drupal\Core\Field\FieldDefinitionInterface $field_definition, $view_mode, $form, $form_state) {
+  $third_party_settings = $plugin->getSetting('third_party_settings');
+  $element['field_test_field_formatter_third_party_settings_form'] = array(
     '#type' => 'textfield',
-    '#title' => t('Formatter settings form alter'),
-    '#default_value' => $context['formatter']->getSetting('field_test_formatter_settings_form_alter'),
+    '#title' => t('3rd party formatter settings form'),
+    '#default_value' => $third_party_settings['field_test'],
   );
+  return $element;
 }
 
 /**
diff --git a/core/modules/field_ui/field_ui.api.php b/core/modules/field_ui/field_ui.api.php
index 255ce85..b2b8d4e 100644
--- a/core/modules/field_ui/field_ui.api.php
+++ b/core/modules/field_ui/field_ui.api.php
@@ -11,65 +11,78 @@
  */
 
 /**
- * Alters the formatter settings form.
+ * Allow modules to add settings to field formatters provided by other modules.
  *
- * @param $element
- *   Form array.
- * @param $form_state
- *   The form state of the (entire) configuration form.
- * @param $context
- *   An associative array with the following elements:
- *   - formatter: The formatter object.
- *   - field_definition: The field definition.
- *   - view_mode: The view mode being configured.
- *   - form: The (entire) configuration form array.
+ * @param object $plugin
+ *   The field formatter.
+ * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
+ *   The field definition.
+ * @param $view_mode
+ *   The entity view mode.
+ * @param array $form
+ *   The The (entire) configuration form array.
+ * @param array $form_state
+ *   The form state.
+ *
+ * @return array
+ *   Returns the form array to be built.
  *
  * @see \Drupal\field_ui\DisplayOverView.
  */
-function hook_field_formatter_settings_form_alter(&$element, &$form_state, $context) {
-  // Add a 'mysetting' checkbox to the settings form for 'foo_formatter'
-  // field formatters.
-  if ($context['formatter']->getPluginId() == 'foo_formatter') {
-    $element['mysetting'] = array(
+function hook_field_formatter_third_party_settings_form($plugin, \Drupal\Core\Field\FieldDefinitionInterface $field_definition, $view_mode, $form, $form_state) {
+  $element = array();
+  // Add a 'my_setting' checkbox to the settings form for 'foo_formatter' field
+  // formatters.
+  if ($plugin->getPluginId() == 'foo_formatter') {
+    $third_party_settings = $plugin->getSetting('third_party_settings');
+    $element['my_setting'] = array(
       '#type' => 'checkbox',
       '#title' => t('My setting'),
-      '#default_value' => $context['formatter']->getSetting('mysetting'),
+      '#default_value' => $third_party_settings['my_setting'],
     );
   }
+  return $element;
 }
 
 /**
- * Alters the widget settings form.
+ * Allow modules to add settings to field widgets provided by other modules.
  *
- * @param array $element
- *   Form array.
+ * @param object $plugin
+ *   The field widget.
+ * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
+ *   The field definition.
+ * @param $form_mode
+ *   The entity form mode.
+ * @param array $form
+ *   The The (entire) configuration form array.
  * @param array $form_state
- *   The form state of the (entire) configuration form.
- * @param array $context
- *   An associative array with the following elements:
- *   - formatter: The formatter object.
- *   - field_definition: The field definition.
- *   - form_mode: The form mode being configured.
- *   - form: The (entire) configuration form array.
+ *   The form state.
+ *
+ * @return array
+ *   Returns the form array to be built.
  *
  * @see \Drupal\field_ui\FormDisplayOverView.
  */
-function hook_field_widget_settings_form_alter(&$element, &$form_state, $context) {
-  // Add a 'mysetting' checkbox to the settings form for 'foo_field' fields.
-  if ($context['field']['type'] == 'foo_field') {
-    $element['mysetting'] = array(
+function hook_field_widget_third_party_settings_form($plugin, \Drupal\Core\Field\FieldDefinitionInterface $field_definition, $form_mode, $form, $form_state) {
+  $element = array();
+  // Add a 'my_setting' checkbox to the settings form for 'foo_widget' field
+  // widgets.
+  if ($plugin->getPluginId() == 'foo_widget') {
+    $third_party_settings = $plugin->getSetting('third_party_settings');
+    $element['my_setting'] = array(
       '#type' => 'checkbox',
       '#title' => t('My setting'),
-      '#default_value' => $context['formatter']->getSetting('mysetting'),
+      '#default_value' => $third_party_settings['my_setting'],
     );
   }
+  return $element;
 }
 
 /**
  * Alters the field formatter settings summary.
  *
- * @param $summary
- *   The summary.
+ * @param array $summary
+ *   An array of summary messages.
  * @param $context
  *   An associative array with the following elements:
  *   - formatter: The formatter object.
@@ -82,7 +95,8 @@ function hook_field_formatter_settings_summary_alter(&$summary, $context) {
   // Append a message to the summary when an instance of foo_formatter has
   // mysetting set to TRUE for the current view mode.
   if ($context['formatter']->getPluginId() == 'foo_formatter') {
-    if ($context['formatter']->getSetting('mysetting')) {
+    $third_party_settings = $plugin->getSetting('third_party_settings');
+    if (isset($third_party_settings['my_setting']) && $third_party_settings['my_setting']) {
       $summary[] = t('My setting enabled.');
     }
   }
@@ -92,7 +106,7 @@ function hook_field_formatter_settings_summary_alter(&$summary, $context) {
  * Alters the field widget settings summary.
  *
  * @param array $summary
- *   The summary.
+ *   An array of summary messages.
  * @param array $context
  *   An associative array with the following elements:
  *   - widget: The widget object.
@@ -102,10 +116,11 @@ function hook_field_formatter_settings_summary_alter(&$summary, $context) {
  * @see \Drupal\field_ui\FormDisplayOverView.
  */
 function hook_field_widget_settings_summary_alter(&$summary, $context) {
-  // Append a message to the summary when an instance of foo_field has
+  // Append a message to the summary when an instance of foo_widget has
   // mysetting set to TRUE for the current view mode.
-  if ($context['field']['type'] == 'foo_field') {
-    if ($context['widget']->getSetting('mysetting')) {
+  if ($context['widget']->getPluginId() == 'foo_widget') {
+    $third_party_settings = $plugin->getSetting('third_party_settings');
+    if (isset($third_party_settings['my_setting']) && $third_party_settings['my_setting']) {
       $summary[] = t('My setting enabled.');
     }
   }
diff --git a/core/modules/field_ui/src/DisplayOverview.php b/core/modules/field_ui/src/DisplayOverview.php
index 956d15f..149aed4 100644
--- a/core/modules/field_ui/src/DisplayOverview.php
+++ b/core/modules/field_ui/src/DisplayOverview.php
@@ -231,13 +231,18 @@ protected function getFieldLabelOptions() {
    * {@inheritdoc}
    */
   protected function alterSettingsForm(array &$settings_form, $plugin, FieldDefinitionInterface $field_definition, array $form, array &$form_state) {
-    $context = array(
-      'formatter' => $plugin,
-      'field_definition' => $field_definition,
-      'view_mode' => $this->mode,
-      'form' => $form,
-    );
-    $this->moduleHandler->alter('field_formatter_settings_form', $settings_form, $form_state, $context);
+    // Iterate through the modules calling their
+    // field_formatter_third_party_settings_form handlers (if any):
+    foreach ($this->moduleHandler->getImplementations('field_formatter_third_party_settings_form') as $module) {
+      // Index the settings form by module name.
+      $settings_form['third_party'][$module] = $this->moduleHandler->invoke($module, 'field_formatter_third_party_settings_form', array(
+        $plugin,
+        $field_definition,
+        $this->mode,
+        $form,
+        $form_state,
+      ));
+    }
   }
 
   /**
diff --git a/core/modules/field_ui/src/DisplayOverviewBase.php b/core/modules/field_ui/src/DisplayOverviewBase.php
index 2a6f46f..70e6cef 100644
--- a/core/modules/field_ui/src/DisplayOverviewBase.php
+++ b/core/modules/field_ui/src/DisplayOverviewBase.php
@@ -348,7 +348,9 @@ protected function buildFieldRow(FieldDefinitionInterface $field_definition, Ent
       if ($plugin) {
         // Generate the settings form and allow other modules to alter it.
         $settings_form = $plugin->settingsForm($form, $form_state);
-        $this->alterSettingsForm($settings_form, $plugin, $field_definition, $form, $form_state);
+        $additional_settings_form = array();
+        $this->alterSettingsForm($additional_settings_form, $plugin, $field_definition, $form, $form_state);
+        $settings_form += $additional_settings_form;
 
         if ($settings_form) {
           $field_row['plugin']['#cell_attributes'] = array('colspan' => 3);
@@ -524,6 +526,7 @@ public function submitForm(array &$form, array &$form_state) {
 
         // Only save settings actually used by the selected plugin.
         $default_settings = $this->pluginManager->getDefaultSettings($values['type']);
+        $third_party = !empty($settings['third_party']) ? $settings['third_party'] : array();
         $settings = array_intersect_key($settings, $default_settings);
 
         // Default component values.
@@ -533,6 +536,11 @@ public function submitForm(array &$form, array &$form_state) {
           'settings' => $settings
         );
 
+        // Add third party settings.
+        if (!empty($third_party)) {
+          $component_values['third_party_settings'] = $third_party;
+        }
+
         // Only formatters have configurable label visibility.
         if (isset($values['label'])) {
           $component_values['label'] = $values['label'];
diff --git a/core/modules/field_ui/src/FormDisplayOverview.php b/core/modules/field_ui/src/FormDisplayOverview.php
index 7c0a5ff..256daf4 100644
--- a/core/modules/field_ui/src/FormDisplayOverview.php
+++ b/core/modules/field_ui/src/FormDisplayOverview.php
@@ -183,13 +183,18 @@ protected function getOverviewRoute($mode) {
    * {@inheritdoc}
    */
   protected function alterSettingsForm(array &$settings_form, $plugin, FieldDefinitionInterface $field_definition, array $form, array &$form_state) {
-    $context = array(
-      'widget' => $plugin,
-      'field_definition' => $field_definition,
-      'form_mode' => $this->mode,
-      'form' => $form,
-    );
-    $this->moduleHandler->alter('field_widget_settings_form', $settings_form, $form_state, $context);
+    // Iterate through the modules calling their
+    // field_widget_third_party_settings_form handlers (if any):
+    foreach ($this->moduleHandler->getImplementations('field_widget_third_party_settings_form') as $module) {
+      // Index the settings form by module name.
+      $settings_form['third_party'][$module] = $this->moduleHandler->invoke($module, 'field_widget_third_party_settings_form', array(
+        $plugin,
+        $field_definition,
+        $this->mode,
+        $form,
+        $form_state,
+      ));
+    }
   }
 
   /**
diff --git a/core/modules/field_ui/src/Tests/ManageDisplayTest.php b/core/modules/field_ui/src/Tests/ManageDisplayTest.php
index c98d52d..11c10fe 100644
--- a/core/modules/field_ui/src/Tests/ManageDisplayTest.php
+++ b/core/modules/field_ui/src/Tests/ManageDisplayTest.php
@@ -100,13 +100,13 @@ function testFormatterUI() {
     $this->drupalPostAjaxForm(NULL, array(), "field_test_settings_edit");
 
     // Assert that the field added in
-    // field_test_field_formatter_settings_form_alter() is present.
-    $fieldname = 'fields[field_test][settings_edit_form][settings][field_test_formatter_settings_form_alter]';
-    $this->assertField($fieldname, 'The field added in hook_field_formatter_settings_form_alter() is present on the settings form.');
+    // field_test_field_formatter_third_party_settings_form() is present.
+    $fieldname = 'fields[field_test][settings_edit_form][third_party][field_test][field_test_field_formatter_third_party_settings_form]';
+    $this->assertField($fieldname, 'The field added in hook_field_formatter_third_party_settings_form() is present on the settings form.');
     $edit = array($fieldname => 'foo');
     $this->drupalPostAjaxForm(NULL, $edit, "field_test_plugin_settings_update");
 
-    // Confirm that the extra settings are not updated on the settings form.
+    // Confirm that the third party settings are not updated on the settings form.
     $this->drupalPostAjaxForm(NULL, array(), "field_test_settings_edit");
     $this->assertFieldByName($fieldname, '');
 
@@ -193,13 +193,13 @@ public function testWidgetUI() {
     $this->drupalPostAjaxForm(NULL, array(), "field_test_settings_edit");
 
     // Assert that the field added in
-    // field_test_field_widget_settings_form_alter() is present.
-    $fieldname = 'fields[field_test][settings_edit_form][settings][field_test_widget_settings_form_alter]';
-    $this->assertField($fieldname, 'The field added in hook_field_widget_settings_form_alter() is present on the settings form.');
+    // field_test_field_widget_third_party_settings_form() is present.
+    $fieldname = 'fields[field_test][settings_edit_form][third_party][field_test][field_test_field_widget_third_party_settings_form]';
+    $this->assertField($fieldname, 'The field added in hook_field_widget_third_party_settings_form() is present on the settings form.');
     $edit = array($fieldname => 'foo');
     $this->drupalPostAjaxForm(NULL, $edit, "field_test_plugin_settings_update");
 
-    // Confirm that the extra settings are not updated on the settings form.
+    // Confirm that the third party settings are not updated on the settings form.
     $this->drupalPostAjaxForm(NULL, array(), "field_test_settings_edit");
     $this->assertFieldByName($fieldname, '');
   }
