 .../config/optional/rest.resource.entity.node.yml  |  31 +++----
 core/modules/rest/config/schema/rest.schema.yml    |  23 ++++-
 core/modules/rest/rest.install                     |  36 ++++++++
 .../modules/rest/src/Entity/ConfigDependencies.php |  99 +++++++++++++++++----
 .../modules/rest/src/Entity/RestResourceConfig.php |  12 ++-
 ...larityRestResourcesConfigEntitiesUpdateTest.php |  70 +++++++++++++++
 .../Update/RestConfigurationEntitiesUpdateTest.php |   4 +
 .../update/drupal-8.rest-rest_update_8202.php      | Bin 0 -> 4290 bytes
 .../rest.resource.entity.comment_2721595.yml       |  30 +++++++
 .../update/rest.resource.entity.node_2721595.yml   |  29 ++++++
 .../update/rest.resource.entity.user_2721595.yml   |  30 +++++++
 .../src/Tests/System/ResponseGeneratorTest.php     |  13 ++-
 12 files changed, 325 insertions(+), 52 deletions(-)

diff --git a/core/modules/rest/config/optional/rest.resource.entity.node.yml b/core/modules/rest/config/optional/rest.resource.entity.node.yml
index 0cf4d78..39f7713 100644
--- a/core/modules/rest/config/optional/rest.resource.entity.node.yml
+++ b/core/modules/rest/config/optional/rest.resource.entity.node.yml
@@ -1,27 +1,16 @@
 id: entity.node
 plugin_id: 'entity:node'
-granularity: method
+granularity: resource
 configuration:
-  GET:
-    supported_formats:
-      - hal_json
-    supported_auth:
-      - basic_auth
-  POST:
-    supported_formats:
-      - hal_json
-    supported_auth:
-      - basic_auth
-  PATCH:
-    supported_formats:
-      - hal_json
-    supported_auth:
-      - basic_auth
-  DELETE:
-    supported_formats:
-      - hal_json
-    supported_auth:
-      - basic_auth
+  methods:
+    - GET
+    - POST
+    - PATCH
+    - DELETE
+  formats:
+    - hal_json
+  authentication:
+    - basic_auth
 dependencies:
   module:
     - node
diff --git a/core/modules/rest/config/schema/rest.schema.yml b/core/modules/rest/config/schema/rest.schema.yml
index 41bc2bf..080c9c5 100644
--- a/core/modules/rest/config/schema/rest.schema.yml
+++ b/core/modules/rest/config/schema/rest.schema.yml
@@ -8,7 +8,6 @@ rest.settings:
       label: 'Domain of the relation'
 
 # Method-level granularity of REST resource configuration.
-# @todo Add resource-level granularity in https://www.drupal.org/node/2721595.
 rest_resource.method:
   type: mapping
   mapping:
@@ -25,6 +24,28 @@ rest_resource.method:
       type: rest_request
       label: 'DELETE method settings'
 
+rest_resource.resource:
+  type: mapping
+  mapping:
+    methods:
+      type: sequence
+      label: 'Supported methods'
+      sequence:
+        type: string
+        label: 'HTTP method'
+    formats:
+      type: sequence
+      label: 'Supported formats'
+      sequence:
+        type: string
+        label: 'Format'
+    authentication:
+      type: sequence
+      label: 'Supported authentication providers'
+      sequence:
+        type: string
+        label: 'Authentication provider'
+
 rest_request:
   type: mapping
   mapping:
diff --git a/core/modules/rest/rest.install b/core/modules/rest/rest.install
index 601206d..5cdfa6e 100644
--- a/core/modules/rest/rest.install
+++ b/core/modules/rest/rest.install
@@ -5,6 +5,8 @@
  * Install, update and uninstall functions for the rest module.
  */
 
+use Drupal\rest\Entity\RestResourceConfig;
+
 /**
  * Implements hook_requirements().
  */
@@ -40,5 +42,39 @@ function rest_update_8201() {
 }
 
 /**
+ * Simplify method-granularity REST resources to resource-granularity.
+ */
+function rest_update_8202() {
+  $config_factory = \Drupal::configFactory();
+
+  foreach ($config_factory->listAll('rest.resource.') as $resource_config_name) {
+    $resource_config_entity = $config_factory->getEditable($resource_config_name);
+
+    if ($resource_config_entity->get('granularity') === 'method') {
+      $configuration = $resource_config_entity->get('configuration');
+
+      $format_and_auth_configuration = [];
+      foreach (array_keys($configuration) as $method) {
+        $format_and_auth_configuration['format'][$method] = implode(',', $configuration[$method]['supported_formats']);
+        $format_and_auth_configuration['auth'][$method] = implode(',', $configuration[$method]['supported_auth']);
+      }
+
+      // If each method has the same formats and the same authentication
+      // providers configured, convert it to 'granularity: resource', which has
+      // a simpler/less verbose configuration.
+      if (count(array_unique($format_and_auth_configuration['format'])) === 1 && count(array_unique($format_and_auth_configuration['auth'])) === 1) {
+        $resource_config_entity->set('configuration', [
+          'methods' => array_keys($configuration),
+          'formats' => $configuration['GET']['supported_formats'],
+          'authentication' => $configuration['GET']['supported_auth']
+        ]);
+        $resource_config_entity->set('granularity', 'resource');
+        $resource_config_entity->save(TRUE);
+      }
+    }
+  }
+}
+
+/**
  * @} End of "defgroup updates-8.1.x-to-8.2.x".
  */
diff --git a/core/modules/rest/src/Entity/ConfigDependencies.php b/core/modules/rest/src/Entity/ConfigDependencies.php
index 72fc8cc..5629141 100644
--- a/core/modules/rest/src/Entity/ConfigDependencies.php
+++ b/core/modules/rest/src/Entity/ConfigDependencies.php
@@ -61,31 +61,21 @@ public static function create(ContainerInterface $container) {
    */
   public function calculateDependencies(RestResourceConfigInterface $rest_config) {
     $granularity = $rest_config->get('granularity');
+
+    // Dependency calculation is the same for either granularity, the most
+    // notable difference is that for the 'resource' granularity, the same
+    // authentication providers and formats are supported for every method.
     if ($granularity === RestResourceConfigInterface::METHOD_GRANULARITY) {
-      return $this->calculateDependenciesForMethodGranularity($rest_config);
+      $methods = array_keys($rest_config->get('configuration'));
     }
     else {
-      throw new \InvalidArgumentException("A different granularity then 'method' is not supported yet.");
-      // @todo Add resource-level granularity support in https://www.drupal.org/node/2721595.
+      $methods = ['GET'];
     }
-  }
 
-  /**
-   * Calculates dependencies of a specific rest resource configuration.
-   *
-   * @param \Drupal\rest\RestResourceConfigInterface $rest_config
-   *   The rest configuration.
-   *
-   * @return string[][]
-   *   Dependencies keyed by dependency type.
-   *
-   * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::calculateDependencies()
-   */
-  protected function calculateDependenciesForMethodGranularity(RestResourceConfigInterface $rest_config) {
     // The dependency lists for authentication providers and formats
     // generated on container build.
     $dependencies = [];
-    foreach (array_keys($rest_config->get('configuration')) as $request_method) {
+    foreach ($methods as $request_method) {
       // Add dependencies based on the supported authentication providers.
       foreach ($rest_config->getAuthenticationProviders($request_method) as $auth) {
         if (isset($this->authProviders[$auth])) {
@@ -125,8 +115,7 @@ public function onDependencyRemoval(RestResourceConfigInterface $rest_config, ar
       return $this->onDependencyRemovalForMethodGranularity($rest_config, $dependencies);
     }
     else {
-      throw new \InvalidArgumentException("A different granularity then 'method' is not supported yet.");
-      // @todo Add resource-level granularity support in https://www.drupal.org/node/2721595.
+      return $this->onDependencyRemovalForResourceGranularity($rest_config, $dependencies);
     }
   }
 
@@ -196,4 +185,76 @@ protected function onDependencyRemovalForMethodGranularity(RestResourceConfigInt
     return $changed;
   }
 
+  /**
+   * Informs the entity that entities it depends on will be deleted.
+   *
+   * @param \Drupal\rest\RestResourceConfigInterface $rest_config
+   *   The rest configuration.
+   * @param array $dependencies
+   *   An array of dependencies that will be deleted keyed by dependency type.
+   *   Dependency types are, for example, entity, module and theme.
+   *
+   * @return bool
+   *   TRUE if the entity has been changed as a result, FALSE if not.
+   */
+  public function onDependencyRemovalForResourceGranularity(RestResourceConfigInterface $rest_config, array $dependencies) {
+    $changed = FALSE;
+    // Only module-related dependencies can be fixed. All other types of
+    // dependencies cannot, because they were not generated based on supported
+    // authentication providers or formats.
+    if (isset($dependencies['module'])) {
+      // Try to fix dependencies.
+      $removed_auth = [];
+      $removed_formats = [];
+      foreach ($dependencies['module'] as $dep_module) {
+        // Check if the removed dependency module contained an authentication
+        // provider.
+        foreach ($this->authProviders as $auth => $auth_module) {
+          if ($dep_module != $auth_module) {
+            continue;
+          }
+          $removed_auth[] = $auth;
+        }
+        // Check if the removed dependency module contained a format.
+        foreach ($this->formatProviders as $format => $format_module) {
+          if ($dep_module != $format_module) {
+            continue;
+          }
+          $removed_formats[] = $format;
+        }
+      }
+      $configuration = $rest_config->get('configuration');
+      if (!empty($removed_auth) || !empty($removed_formats)) {
+        foreach ($removed_formats as $format) {
+          if (in_array($format, $configuration['formats'])) {
+            $configuration = array_filter($configuration['formats'], function ($val) use ($format) {
+              return $val !== $format;
+            });
+          }
+        }
+        foreach ($removed_auth as $auth) {
+          if (in_array($auth, $configuration['authentication'])) {
+            $configuration = array_filter($configuration['authentication'], function ($val) use ($auth) {
+              return $val !== $auth;
+            });
+          }
+        }
+        // Only mark the dependencies problems as fixed if there is still >=1
+        // format available and >=1 authentication provider available.
+        if (!empty($configuration['formats']) && !empty($configuration['authentication'])) {
+          $changed = TRUE;
+        }
+      }
+      else {
+        // Dependencies were removed, but they did not affect the formats or
+        // authentication providers used by this entity.
+        $changed = TRUE;
+      }
+    }
+    // If the dependency problems are not marked as fixed at this point they
+    // should be related to the resource plugin and the config entity should
+    // be deleted.
+    return $changed;
+  }
+
 }
diff --git a/core/modules/rest/src/Entity/RestResourceConfig.php b/core/modules/rest/src/Entity/RestResourceConfig.php
index f2b8b0e..708fae8 100644
--- a/core/modules/rest/src/Entity/RestResourceConfig.php
+++ b/core/modules/rest/src/Entity/RestResourceConfig.php
@@ -3,6 +3,7 @@
 namespace Drupal\rest\Entity;
 
 use Drupal\Core\Config\Entity\ConfigEntityBase;
+use Drupal\Core\Entity\Entity;
 use Drupal\Core\Plugin\DefaultSingleLazyPluginCollection;
 use Drupal\rest\RestResourceConfigInterface;
 
@@ -45,7 +46,7 @@ class RestResourceConfig extends ConfigEntityBase implements RestResourceConfigI
   /**
    * The REST resource configuration granularity.
    *
-   * @todo Currently only 'method', but https://www.drupal.org/node/2721595 will add 'resource'
+   * Currently either 'method' or 'resource'.
    *
    * @var string
    */
@@ -116,8 +117,7 @@ public function getMethods() {
       return $this->getMethodsForMethodGranularity();
     }
     else {
-      throw new \InvalidArgumentException("A different granularity then 'method' is not supported yet.");
-      // @todo Add resource-level granularity support in https://www.drupal.org/node/2721595.
+      return $this->configuration['methods'];
     }
   }
 
@@ -140,8 +140,7 @@ public function getAuthenticationProviders($method) {
       return $this->getAuthenticationProvidersForMethodGranularity($method);
     }
     else {
-      throw new \InvalidArgumentException("A different granularity then 'method' is not supported yet.");
-      // @todo Add resource-level granularity support in https://www.drupal.org/node/2721595.
+      return $this->configuration['authentication'];
     }
   }
 
@@ -170,8 +169,7 @@ public function getFormats($method) {
       return $this->getFormatsForMethodGranularity($method);
     }
     else {
-      throw new \InvalidArgumentException("A different granularity then 'method' is not supported yet.");
-      // @todo Add resource-level granularity support in https://www.drupal.org/node/2721595.
+      return $this->configuration['formats'];
     }
   }
 
diff --git a/core/modules/rest/src/Tests/Update/ResourceGranularityRestResourcesConfigEntitiesUpdateTest.php b/core/modules/rest/src/Tests/Update/ResourceGranularityRestResourcesConfigEntitiesUpdateTest.php
new file mode 100644
index 0000000..3dda20d
--- /dev/null
+++ b/core/modules/rest/src/Tests/Update/ResourceGranularityRestResourcesConfigEntitiesUpdateTest.php
@@ -0,0 +1,70 @@
+<?php
+
+namespace Drupal\rest\Tests\Update;
+
+use Drupal\system\Tests\Update\UpdatePathTestBase;
+
+/**
+ * Tests rest_resource_config entities are simplified when possible.
+ *
+ * @see https://www.drupal.org/node/2721595
+ *
+ * @group rest
+ */
+class ResourceGranularityRestResourcesConfigEntitiesUpdateTest extends UpdatePathTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['rest', 'serialization'];
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setDatabaseDumpFiles() {
+    $this->databaseDumpFiles = [
+      __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
+      __DIR__ . '/../../../../rest/tests/fixtures/update/drupal-8.rest-rest_update_8202.php',
+    ];
+  }
+
+  /**
+   * Tests rest_update_8202().
+   */
+  public function testResourcesConvertedToConfigEntities() {
+    /** @var \Drupal\Core\Entity\EntityStorageInterface $resource_config_storage */
+    $resource_config_storage = $this->container->get('entity_type.manager')->getStorage('rest_resource_config');
+
+    // Make sure we have the expected values before the update.
+    $resource_config_entities = $resource_config_storage->loadMultiple();
+    $this->assertIdentical(['entity.comment', 'entity.node', 'entity.user'], array_keys($resource_config_entities));
+    $this->assertIdentical('method', $resource_config_entities['entity.node']->get('granularity'));
+    $this->assertIdentical('method', $resource_config_entities['entity.comment']->get('granularity'));
+    $this->assertIdentical('method', $resource_config_entities['entity.user']->get('granularity'));
+
+    // Read the existing 'entity:comment' and 'entity:user' resource
+    // configuration so we can verify it after the update.
+    $comment_resource_configuration = $resource_config_entities['entity.comment']->get('configuration');
+    $user_resource_configuration = $resource_config_entities['entity.user']->get('configuration');
+
+    $this->runUpdates();
+
+    // Make sure we have the expected values after the update.
+    $resource_config_entities = $resource_config_storage->loadMultiple();
+    $this->assertIdentical(['entity.comment', 'entity.node', 'entity.user'], array_keys($resource_config_entities));
+    // 'entity:node' should be updated.
+    $this->assertIdentical('resource', $resource_config_entities['entity.node']->get('granularity'));
+    $this->assertidentical($resource_config_entities['entity.node']->get('configuration'), [
+      'methods' => ['GET', 'POST', 'PATCH', 'DELETE'],
+      'formats' => ['hal_json'],
+      'authentication' => ['basic_auth'],
+    ]);
+    // 'entity:comment' should be unchanged.
+    $this->assertIdentical('method', $resource_config_entities['entity.comment']->get('granularity'));
+    $this->assertIdentical($comment_resource_configuration, $resource_config_entities['entity.comment']->get('configuration'));
+    // 'entity:user' should be unchanged.
+    $this->assertIdentical('method', $resource_config_entities['entity.user']->get('granularity'));
+    $this->assertIdentical($user_resource_configuration, $resource_config_entities['entity.user']->get('configuration'));
+  }
+
+}
diff --git a/core/modules/rest/src/Tests/Update/RestConfigurationEntitiesUpdateTest.php b/core/modules/rest/src/Tests/Update/RestConfigurationEntitiesUpdateTest.php
index 9100f16..fa08f48 100644
--- a/core/modules/rest/src/Tests/Update/RestConfigurationEntitiesUpdateTest.php
+++ b/core/modules/rest/src/Tests/Update/RestConfigurationEntitiesUpdateTest.php
@@ -58,6 +58,10 @@ public function testResourcesConvertedToConfigEntities() {
     $this->assertIdentical(RestResourceConfigInterface::METHOD_GRANULARITY, $node_resource_config_entity->get('granularity'));
     $this->assertIdentical($node_configuration, $node_resource_config_entity->get('configuration'));
     $this->assertIdentical(['module' => ['basic_auth', 'node', 'serialization']], $node_resource_config_entity->getDependencies());
+    $this->assertIdentical(['entity.node'], array_keys($resource_config_entities));
+    $node_resource_config_entity = $resource_config_entities['entity.node'];
+    $this->assertIdentical('method', $node_resource_config_entity->get('granularity'));
+    $this->assertIdentical($node_configuration,$node_resource_config_entity->get('configuration'));
   }
 
 }
diff --git a/core/modules/rest/tests/fixtures/update/drupal-8.rest-rest_update_8202.php b/core/modules/rest/tests/fixtures/update/drupal-8.rest-rest_update_8202.php
new file mode 100644
index 0000000000000000000000000000000000000000..433d021b200d1428e1ebe640efb59f48dc9c9274
GIT binary patch
literal 4290
zcmcIn+iu)85Y6*`1tA2`+VINWwR6)p+ZJ|$7HHEVP9F+85NL_J7EE10QI4G;|K2kk
zN|rV@(4z4}94$GV%b7F7;SWF7m-S?_zq>mTyW*#Ht`&V8SEZGC*@#S9c_AAmWR~SN
zudrk*k(suZdiFB9kVZv~m1QPP7C}|C`7G9z5mq%eFE_$oI(==uF)~x4miAIqYhkdR
zv^BJ=<mKXEG2Mw^c7HNyVd}(bKR>RDx++y^&rg-frOrP~a^U=LS?J|h(5Ukh?`Z$A
zoJ^jkRavT(PKno|lZfMuvIx-cOm`r;zb{UeC2vKOUaCThYh@aoi-t;OD?p-*orYKH
zHo2C%RpHJ=h}mkLE1fmdGyD)DOe?L~Y$#r@MA+OmRuvIz4)<87l!fAL0;5}HrS4Q7
z1DW~K?R@+WX5jf9ivP}@x>0FsRR_^uE@2|AkaTrpRp}AxzZ<|j0DZP<6ag^>BIP>Y
zjKS&__rzI9Gz)!@kY%dTu^z}h5&GkUeTN}-#vXaO-g(ZDvgzepN)tu%bmVeNS#{W`
z>0oCpcNP{^)@l`gJPTdMJ|b9`p`o^+RHxL@HXMi}0#Cl#ii_ZWggl)bI7Ep~;n+*!
z(_=w5E~440P-dgPrT-u$<CLL#b9)<QYMqzdJ|dKml}Ky$a5`Ogz@Mr$sY;+6+=*CK
zVsGpFi*8Ukf5b<NIOy95y2G*4asI}+<A3pw56~CHhp*x<O+0@d2TyjNu)(A@@cJfL
zHu1|i=)9qy^Jh*BVc0xPQi+BUEHB~%+B$Mux~i_)Izg9cf~Ab-@t53fW4CSdELeWs
zHl}Xs%2*OU>Vy#jiRSSfieJS+t=mmrCcL&FWAivbTP<5H4NxZ0Ls~wJ0}i1zj(X1A
z0>X&RB`{++-t;yP;xFV8$7NKRDRUPWnV-WxPS?~F(aTD^wasDs6m?-gCro`5gAa%1
zbxys5&^(9(`VY`wv}L9NWxobVEz3<>Wo~urCuIx7lC8GMQ0$@g9{dIv-{paWCRE`g
zoVkyDv`1(Y1g5&qfe$S~4N21{d?V&)*&yRheE6d0A4zn?dyjAYbG+spIL%DE%H+te
z)W@vk-JQ)#+^-tY6Fn9LDh|jrRcz}B5e&KRNzVWM?8IQpno9q|ddMdHYiwoY#v!|{
zf_>|}_H1#rbJ`suzA!0dR)ChEMv*sNQWx;atrJ^}yYA_a3)}%j0!%1>Dj6}E;r4u@
zlE1@P=jD|{!jl$}K#`UgN`sVIU&!>zp^B8?qW_IH-kPfT)0GeH_)=iHB_ksabWj!=
z{dTnumTr|D_N&gE-$1#MIEJJIvl0=Q<QJ^PC}w&>O?<dNXTSUX!BHw;X#C~`dtg!V
zjizabOmW*`_Ian!{qTFph*N7Yi+%71X@=^)Ny+chpjn{@60<m^jXU75LPflPbNZpr
z9&UeX#|~i*QJPI#0L5Waa0(GrwVN1;wv;TQ%rILGoTA=Ex_lS#Er_#;hG(Q6?sA*q
z-Lz^;*Dy!Tt2Oz61(XQJW@9SEh@ba#M=Y{pCxl)C#stgn3L{zNGU|IWto{f5aD}*{
z1^O1Vi;DzUa*+$F5aB~4m_7O2RGPGT;>ZaEY)4M+IB8WBRhi(PQ)v3QYAtf9pqyFd
zwP@5Zw|lyZ$@(zUo_cpOR&LyWf9V|}OeRfCy%6R`7kfhb`9|a{Ko<PN>tkexYodFF
z5G|Ng+_XV9=4?l7ce%V<e(mPm@wC0|!)Unh^Z8(qapO4mi3diR!3@@qo!hfh_jX_`
z#<TFZ4~O9^!GF6su(yOK%L(6pz9c=f@Q}iT#7#pFK1l9ICF(NM!I6}>c{|yArcio`
z#c`(Sf}YaTF#&s+BuL&gNlt!!pClp@;XY-4TYp6Alf{e0{MoB#(QTo_ot>Rwe8(;B
zsA3%6p7@mG4Ov!JG<ZSLW3!O95qRRE`S)$A`JOOPogn>>h=jNBf5DI~Ua+{QQ#bcL
VDkgZSn@0qM)IW&EY&9sde*o#3T8IDu

literal 0
HcmV?d00001

diff --git a/core/modules/rest/tests/fixtures/update/rest.resource.entity.comment_2721595.yml b/core/modules/rest/tests/fixtures/update/rest.resource.entity.comment_2721595.yml
new file mode 100644
index 0000000..15f81be
--- /dev/null
+++ b/core/modules/rest/tests/fixtures/update/rest.resource.entity.comment_2721595.yml
@@ -0,0 +1,30 @@
+id: entity.comment
+plugin_id: 'entity:comment'
+granularity: method
+configuration:
+  GET:
+    supported_formats:
+      - hal_json
+      - xml
+    supported_auth:
+      - basic_auth
+  POST:
+    supported_formats:
+      - hal_json
+    supported_auth:
+      - basic_auth
+  PATCH:
+    supported_formats:
+      - hal_json
+    supported_auth:
+      - basic_auth
+  DELETE:
+    supported_formats:
+      - hal_json
+    supported_auth:
+      - basic_auth
+dependencies:
+  module:
+    - node
+    - basic_auth
+    - hal
diff --git a/core/modules/rest/tests/fixtures/update/rest.resource.entity.node_2721595.yml b/core/modules/rest/tests/fixtures/update/rest.resource.entity.node_2721595.yml
new file mode 100644
index 0000000..0cf4d78
--- /dev/null
+++ b/core/modules/rest/tests/fixtures/update/rest.resource.entity.node_2721595.yml
@@ -0,0 +1,29 @@
+id: entity.node
+plugin_id: 'entity:node'
+granularity: method
+configuration:
+  GET:
+    supported_formats:
+      - hal_json
+    supported_auth:
+      - basic_auth
+  POST:
+    supported_formats:
+      - hal_json
+    supported_auth:
+      - basic_auth
+  PATCH:
+    supported_formats:
+      - hal_json
+    supported_auth:
+      - basic_auth
+  DELETE:
+    supported_formats:
+      - hal_json
+    supported_auth:
+      - basic_auth
+dependencies:
+  module:
+    - node
+    - basic_auth
+    - hal
diff --git a/core/modules/rest/tests/fixtures/update/rest.resource.entity.user_2721595.yml b/core/modules/rest/tests/fixtures/update/rest.resource.entity.user_2721595.yml
new file mode 100644
index 0000000..be2a607
--- /dev/null
+++ b/core/modules/rest/tests/fixtures/update/rest.resource.entity.user_2721595.yml
@@ -0,0 +1,30 @@
+id: entity.user
+plugin_id: 'entity:user'
+granularity: method
+configuration:
+  GET:
+    supported_formats:
+      - hal_json
+    supported_auth:
+      - basic_auth
+      - oauth
+  POST:
+    supported_formats:
+      - hal_json
+    supported_auth:
+      - basic_auth
+  PATCH:
+    supported_formats:
+      - hal_json
+    supported_auth:
+      - basic_auth
+  DELETE:
+    supported_formats:
+      - hal_json
+    supported_auth:
+      - basic_auth
+dependencies:
+  module:
+    - node
+    - basic_auth
+    - hal
diff --git a/core/modules/system/src/Tests/System/ResponseGeneratorTest.php b/core/modules/system/src/Tests/System/ResponseGeneratorTest.php
index d0d22a2..d2f8f5f 100644
--- a/core/modules/system/src/Tests/System/ResponseGeneratorTest.php
+++ b/core/modules/system/src/Tests/System/ResponseGeneratorTest.php
@@ -53,13 +53,18 @@ function testGeneratorHeaderAdded() {
     $this->assertEqual('text/html; charset=UTF-8', $this->drupalGetHeader('Content-Type'));
     $this->assertEqual($expectedGeneratorHeader, $this->drupalGetHeader('X-Generator'));
 
-    // Enable rest API for nodes
-    $this->enableService('entity:node', 'GET', 'json');
+    // Enable cookie-based authentication for the entity:node REST resource.
+    /** @var \Drupal\rest\RestResourceConfigInterface $resource_config */
+    $resource_config = $this->resourceConfigStorage->load('entity.node');
+    $configuration = $resource_config->get('configuration');
+    $configuration['authentication'][] = 'cookie';
+    $resource_config->set('configuration', $configuration)->save();
+    $this->rebuildCache();
 
     // Tests to see if this also works for a non-html request
-    $this->httpRequest($node->urlInfo()->setOption('query', ['_format' => 'json']), 'GET');
+    $this->httpRequest($node->urlInfo()->setOption('query', ['_format' => 'hal_json']), 'GET');
     $this->assertResponse(200);
-    $this->assertEqual('application/json', $this->drupalGetHeader('Content-Type'));
+    $this->assertEqual('application/hal+json', $this->drupalGetHeader('Content-Type'));
     $this->assertEqual($expectedGeneratorHeader, $this->drupalGetHeader('X-Generator'));
 
   }
