.../EntityResource/User/UserResourceTestBase.php   | 103 +++++++++++++++++++++
 1 file changed, 103 insertions(+)
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/User/UserResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/User/UserResourceTestBase.php
index 478c442..ef04868 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/User/UserResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/User/UserResourceTestBase.php
@@ -2,8 +2,10 @@
 
 namespace Drupal\Tests\rest\Functional\EntityResource\User;
 
+use Drupal\Core\Url;
 use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
 use Drupal\user\Entity\User;
+use GuzzleHttp\RequestOptions;
 
 abstract class UserResourceTestBase extends EntityResourceTestBase {
 
@@ -119,4 +121,105 @@ protected function getNormalizedPostEntity() {
     ];
   }
 
+  /**
+   * Tests PATCHing security-sensitive base fields of the logged in account.
+   */
+  public function testPatchDxForSecuritySensitiveBaseFields() {
+    // The anonymous user is never allowed to modify itself.
+    if (!static::$auth) {
+      $this->markTestSkipped();
+    }
+
+    $this->initAuthentication();
+    $this->provisionEntityResource();
+    $this->setUpAuthorization('PATCH');
+
+    /** @var \Drupal\user\UserInterface $user */
+    $user = static::$auth ? $this->account : User::load(0);
+    $original_normalization = array_diff_key($this->serializer->normalize($user, static::$format), ['changed' => TRUE]);
+
+
+    // Since this test must be performed by the user that is being modified,
+    // we cannot use $this->getUrl().
+    $url = $user->toUrl()->setOption('query', ['_format' => static::$format]);
+    $request_options = [
+      RequestOptions::HEADERS => ['Content-Type' => static::$mimeType],
+    ];
+    $request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('PATCH'));
+
+
+    // Test case 1: changing email.
+    $normalization = $original_normalization;
+    $normalization['mail'] = [['value' => 'new-email@example.com']];
+    $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
+
+
+    // DX: 422 when changing email without providing the password.
+    $response = $this->request('PATCH', $url, $request_options);
+    // @todo use this commented line instead of the 3 lines thereafter once https://www.drupal.org/node/2813755 lands.
+//    $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nmail: Your current password is missing or incorrect; it's required to change the Email.\n", $response);
+    $this->assertSame(422, $response->getStatusCode());
+    $this->assertSame([static::$mimeType], $response->getHeader('Content-Type'));
+    $this->assertSame($this->serializer->encode(['message' => "Unprocessable Entity: validation failed.\nmail: Your current password is missing or incorrect; it's required to change the Email.\n"], static::$format), (string) $response->getBody());
+
+
+    $normalization['pass'] = [['existing' => 'wrong']];
+    $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
+
+    // DX: 422 when changing email while providing a wrong password.
+    $response = $this->request('PATCH', $url, $request_options);
+    // @todo use this commented line instead of the 3 lines thereafter once https://www.drupal.org/node/2813755 lands.
+//    $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nmail: Your current password is missing or incorrect; it's required to change the Email.\n", $response);
+    $this->assertSame(422, $response->getStatusCode());
+    $this->assertSame([static::$mimeType], $response->getHeader('Content-Type'));
+    $this->assertSame($this->serializer->encode(['message' => "Unprocessable Entity: validation failed.\nmail: Your current password is missing or incorrect; it's required to change the Email.\n"], static::$format), (string) $response->getBody());
+
+
+    $normalization['pass'] = [['existing' => $this->account->passRaw]];
+    $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
+
+
+    // 200 for well-formed request.
+    $response = $this->request('PATCH', $url, $request_options);
+    $this->assertResourceResponse(200, FALSE, $response);
+
+
+    // Test case 2: changing password.
+    $normalization = $original_normalization;
+    $new_password = $this->randomString();
+    $normalization['pass'] = [['value' => $new_password]];
+    $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
+
+
+    // DX: 422 when changing password without providing the current password.
+    $response = $this->request('PATCH', $url, $request_options);
+    // @todo use this commented line instead of the 3 lines thereafter once https://www.drupal.org/node/2813755 lands.
+//    $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\npass: Your current password is missing or incorrect; it's required to change the Password.\n", $response);
+    $this->assertSame(422, $response->getStatusCode());
+    $this->assertSame([static::$mimeType], $response->getHeader('Content-Type'));
+    $this->assertSame($this->serializer->encode(['message' => "Unprocessable Entity: validation failed.\npass: Your current password is missing or incorrect; it's required to change the Password.\n"], static::$format), (string) $response->getBody());
+
+
+    $normalization['pass'][0]['existing'] = $this->account->pass_raw;
+    $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
+
+
+    // 200 for well-formed request.
+    $response = $this->request('PATCH', $url, $request_options);
+    $this->assertResourceResponse(200, FALSE, $response);
+
+
+    // Verify that we can log in with the new password.
+    $request_body = [
+      'name' => $user->getAccountName(),
+      'pass' => $new_password,
+    ];
+    $request_options = [
+      RequestOptions::HEADERS => [],
+      RequestOptions::BODY => $this->serializer->encode($request_body, 'json'),
+    ];
+    $response = $this->httpClient->request('POST', Url::fromRoute('user.login.http')->setRouteParameter('_format', 'json')->toString(), $request_options);
+    $this->assertSame(200, $response->getStatusCode());
+  }
+
 }