diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/PasswordItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/PasswordItem.php
new file mode 100644
index 0000000..d7d2ded
--- /dev/null
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/PasswordItem.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Field\Plugin\Field\FieldType\PasswordItem.
+ */
+
+namespace Drupal\Core\Field\Plugin\Field\FieldType;
+
+/**
+ * Defines the 'password' entity field type.
+ *
+ * @FieldType(
+ *   id = "password",
+ *   label = @Translation("Password"),
+ *   description = @Translation("An entity field containing a password value."),
+ *   no_ui = TRUE,
+ *   default_widget = "string",
+ *   default_formatter = "string"
+ * )
+ */
+class PasswordItem extends StringItem {}
diff --git a/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php b/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php
index 6a24454..e414892 100644
--- a/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php
+++ b/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php
@@ -90,7 +90,13 @@ public function normalize($entity, $format = NULL, array $context = array()) {
     // Ignore the entity ID and revision ID.
     $exclude = array($entity->getEntityType()->getKey('id'), $entity->getEntityType()->getKey('revision'));
     foreach ($fields as $field) {
-      if (in_array($field->getFieldDefinition()->getName(), $exclude)) {
+      $field_name = $field->getFieldDefinition()->getName();
+      if (in_array($field_name, $exclude)) {
+        continue;
+      }
+      $field = $entity->get($field_name);
+      if (method_exists($field, 'getFieldDefinition') && ($definition = $field->getFieldDefinition()) && $definition->getType() == 'password') {
+        // Never normalize password items.
         continue;
       }
       $normalized_property = $this->serializer->normalize($field, $format, $context);
diff --git a/core/modules/hal/src/Tests/EntityTest.php b/core/modules/hal/src/Tests/EntityTest.php
index a115146..2ba9afa 100644
--- a/core/modules/hal/src/Tests/EntityTest.php
+++ b/core/modules/hal/src/Tests/EntityTest.php
@@ -6,6 +6,7 @@
  */
 
 namespace Drupal\hal\Tests;
+use Drupal\user\Entity\User;
 
 /**
  * Tests that nodes and terms are correctly normalized and denormalized.
@@ -19,7 +20,7 @@ class EntityTest extends NormalizerTestBase {
    *
    * @var array
    */
-  public static $modules = array('node', 'taxonomy', 'comment');
+  public static $modules = array('node', 'taxonomy', 'comment', 'user');
 
   /**
    * {@inheritdoc}
@@ -31,6 +32,7 @@ protected function setUp() {
     $this->installSchema('system', array('sequences'));
     $this->installSchema('comment', array('comment_entity_statistics'));
     $this->installEntitySchema('comment');
+    $this->installEntitySchema('user');
     $this->installEntitySchema('taxonomy_term');
   }
 
@@ -208,4 +210,35 @@ public function testComment() {
     }
   }
 
+  /**
+   * Tests the normalization of users.
+   */
+  public function testUser() {
+    // Test password isn't available.
+    $account = User::create([
+      'name' => 'foo',
+      'mail' => 'foo@example.com',
+      'pass' => '123456',
+    ]);
+    $account->save();
+    $original_values = $account->toArray();
+    unset($original_values['uid'], $original_values['pass']);
+
+    $normalized = $this->serializer->normalize($account, $this->format);
+
+    $denormalized_account = $this->serializer->denormalize($normalized, 'Drupal\user\Entity\User', $this->format);
+
+    // Verify that the ID and password were skipped by the normalizer.
+    $this->assertEqual(NULL, $denormalized_account->id());
+    $this->assertEqual(NULL, $denormalized_account->getPassword());
+
+    // Loop over the remaining fields and verify that they are identical.
+    foreach ($original_values as $field_name => $field_values) {
+      if (empty($field_values) || (empty($field_values[0]))) {
+        continue;
+      }
+      $this->assertEqual($field_values, $denormalized_account->get($field_name)->getValue());
+    }
+  }
+
 }
diff --git a/core/modules/serialization/src/Normalizer/ComplexDataNormalizer.php b/core/modules/serialization/src/Normalizer/ComplexDataNormalizer.php
index 9d99d5d..154412b 100644
--- a/core/modules/serialization/src/Normalizer/ComplexDataNormalizer.php
+++ b/core/modules/serialization/src/Normalizer/ComplexDataNormalizer.php
@@ -34,6 +34,10 @@ class ComplexDataNormalizer extends NormalizerBase {
   public function normalize($object, $format = NULL, array $context = array()) {
     $attributes = array();
     foreach ($object as $name => $field) {
+      if (method_exists($field, 'getFieldDefinition') && ($definition = $field->getFieldDefinition()) && $definition->getType() == 'password') {
+        // Never normalize password items.
+        continue;
+      }
       $attributes[$name] = $this->serializer->normalize($field, $format);
     }
     return $attributes;
diff --git a/core/modules/serialization/src/Tests/EntitySerializationTest.php b/core/modules/serialization/src/Tests/EntitySerializationTest.php
index 849b271..db0c944 100644
--- a/core/modules/serialization/src/Tests/EntitySerializationTest.php
+++ b/core/modules/serialization/src/Tests/EntitySerializationTest.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Component\Utility\String;
+use Drupal\user\Entity\User;
 
 /**
  * Tests that entities can be serialized to supported core formats.
@@ -48,6 +49,8 @@ class EntitySerializationTest extends NormalizerTestBase {
   protected function setUp() {
     parent::setUp();
 
+    // User create needs sequence table.
+    $this->installSchema('system', array('sequences'));
     // Create a test entity to serialize.
     $this->values = array(
       'name' => $this->randomMachineName(),
@@ -105,6 +108,16 @@ public function testNormalize() {
       $this->assertEqual($expected[$fieldName], $normalized[$fieldName], "ComplexDataNormalizer produces expected array for $fieldName.");
     }
     $this->assertEqual(array_diff_key($normalized, $expected), array(), 'No unexpected data is added to the normalized array.');
+
+    // Test password isn't available.
+    $account = User::create([
+      'name' => 'foo',
+      'mail' => 'foo@example.com',
+      'pass' => '123456',
+    ]);
+    $account->save();
+    $normalized = $this->serializer->normalize($account);
+    $this->assertTrue(empty($normalized['pass']));
   }
 
   /**
diff --git a/core/modules/user/src/Entity/User.php b/core/modules/user/src/Entity/User.php
index c003db2..70a602f 100644
--- a/core/modules/user/src/Entity/User.php
+++ b/core/modules/user/src/Entity/User.php
@@ -478,7 +478,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
         'UserNameUnique' => array(),
       ));
 
-    $fields['pass'] = BaseFieldDefinition::create('string')
+    $fields['pass'] = BaseFieldDefinition::create('password')
       ->setLabel(t('Password'))
       ->setDescription(t('The password of this user (hashed).'));
 
