diff --git a/core/modules/hal/lib/Drupal/hal/Normalizer/EntityNormalizer.php b/core/modules/hal/lib/Drupal/hal/Normalizer/EntityNormalizer.php
index 751de28..ba15b25 100644
--- a/core/modules/hal/lib/Drupal/hal/Normalizer/EntityNormalizer.php
+++ b/core/modules/hal/lib/Drupal/hal/Normalizer/EntityNormalizer.php
@@ -100,6 +100,10 @@ public function denormalize($data, $class, $format = NULL, array $context = arra
     }
 
     $entity = entity_create($typed_data_ids['entity_type'], array('langcode' => $langcode, 'type' => $typed_data_ids['bundle']));
+    // Make sure that we are always dealing with the real NG object here,
+    // otherwise unexpected things happen when setting fields on the BC
+    // decorator.
+    $entity = $entity->getNGEntity();
 
     // Special handling for PATCH: destroy all possible default values that
     // might have been set on entity creation. We want an "empty" entity that
diff --git a/core/modules/hal/lib/Drupal/hal/Tests/NodeTest.php b/core/modules/hal/lib/Drupal/hal/Tests/NodeTest.php
new file mode 100644
index 0000000..a5b7c89
--- /dev/null
+++ b/core/modules/hal/lib/Drupal/hal/Tests/NodeTest.php
@@ -0,0 +1,93 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\hal\Tests\NodeTest.
+ */
+
+namespace Drupal\hal\Tests;
+
+use Drupal\simpletest\DrupalUnitTestBase;
+
+/**
+ * Test the HAL normalizer's denormalize function on node entities.
+ */
+class NodeTest extends DrupalUnitTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('field', 'field_sql_storage', 'hal', 'system', 'text', 'node', 'rest', 'serialization', 'entity');
+
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Node Denormalization Test',
+      'description' => 'Test that nodes can be denormalized from HAL.',
+      'group' => 'HAL',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  function setUp() {
+    parent::setUp();
+
+    // Create the test field with cardinality one.
+    $field = entity_create('field_entity', array(
+      'field_name' => 'field_test',
+      'type' => 'text_long',
+      'cardinality' => 1,
+      'translatable' => FALSE,
+      'entity_types' => array('node'),
+    ));
+    $field->save();
+
+    $instance = entity_create('field_instance', array(
+      'field_name' => 'field_test',
+      'label' => 'Test',
+      'entity_type' => 'node',
+      'bundle' => 'page',
+      'settings' => array('text_processing' => 1),
+      'required' => FALSE,
+    ));
+    $instance->save();
+
+    // We need a valid and existent content type for testing the entity
+    // denormalizer.
+    $node_type = entity_create('node_type', array(
+      'type' => 'page',
+    ));
+    $node_type->save();
+  }
+
+  /**
+   * Tests that a text field with a cardinality of one can be denormalized.
+   */
+  public function testLimitedFieldCardinality() {
+    $data = array(
+      '_links' => array(
+        'type' => array(
+          'href' => url('rest/type/node/page', array('absolute' => TRUE)),
+        ),
+      ),
+      'field_test' => array(
+        0 => array(
+          'value' => 'testvalue',
+          'format' => 'full_html',
+        ),
+      ),
+    );
+
+    $serializer = $this->container->get('serializer');
+    $node = $serializer->denormalize($data, 'Drupal\node\Plugin\Core\Entity\Node', 'hal_json');
+    $this->assertEqual(count($node->get('field_test')), 1, 'Exactly one field item was created.');
+    $this->assertEqual($node->get('field_test')->getValue(), $data['field_test']);
+  }
+}
diff --git a/core/modules/rest/lib/Drupal/rest/Tests/RESTTestBase.php b/core/modules/rest/lib/Drupal/rest/Tests/RESTTestBase.php
index db8feb2..d6fc9f9 100644
--- a/core/modules/rest/lib/Drupal/rest/Tests/RESTTestBase.php
+++ b/core/modules/rest/lib/Drupal/rest/Tests/RESTTestBase.php
@@ -166,7 +166,10 @@ protected function entityValues($entity_type) {
         return array(
           'name' => $this->randomName(),
           'user_id' => 1,
-          'field_test_text' => array(0 => array('value' => $this->randomString())),
+          'field_test_text' => array(0 => array(
+            'value' => $this->randomString(),
+            'format' => 'plain_text',
+          )),
         );
       case 'node':
         return array('title' => $this->randomString(), 'type' => 'resttest');
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItem.php b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItem.php
index 644a2a9..4fa2ccb 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItem.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItem.php
@@ -25,7 +25,8 @@
  *     "text_processing" = "0"
  *   },
  *   default_widget = "text_textfield",
- *   default_formatter = "text_default"
+ *   default_formatter = "text_default",
+ *   list_class = "Drupal\text\TextField"
  * )
  */
 class TextItem extends TextItemBase {
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextWithSummaryItem.php b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextWithSummaryItem.php
index 8d5c9fb..61141ea 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextWithSummaryItem.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextWithSummaryItem.php
@@ -23,7 +23,8 @@
  *     "display_summary" = "0"
  *   },
  *   default_widget = "text_textarea_with_summary",
- *   default_formatter = "text_default"
+ *   default_formatter = "text_default",
+ *   list_class = "Drupal\text\TextField"
  * )
  */
 class TextWithSummaryItem extends TextItemBase {
diff --git a/core/modules/text/lib/Drupal/text/Tests/AccessTest.php b/core/modules/text/lib/Drupal/text/Tests/AccessTest.php
new file mode 100644
index 0000000..782eff5
--- /dev/null
+++ b/core/modules/text/lib/Drupal/text/Tests/AccessTest.php
@@ -0,0 +1,89 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\text\AccessTest.
+ */
+
+namespace Drupal\text\Tests;
+
+use Drupal\system\Tests\Entity\EntityUnitTestBase;
+
+/**
+ * Tests the text field access method.
+ */
+class AccessTest extends EntityUnitTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('entity', 'user', 'system', 'field', 'text', 'field_sql_storage', 'entity_test', 'filter');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Text Field Access',
+      'description' => 'Tests the text field access method.',
+      'group' => 'Field types',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+
+    $this->installSchema('user', 'users_roles');
+    entity_test_install();
+
+    // Create Filtered HTML format.
+    $filtered_html_format = entity_create('filter_format', array(
+      'format' => 'filtered_html',
+      'name' => 'Filtered HTML',
+      'filters' => array(
+        'filter_html' => array(
+          'status' => 1,
+          'settings' => array(
+            'allowed_html' => '<p> <br> <strong> <a>',
+          ),
+        ),
+      )
+    ));
+    $filtered_html_format->save();
+
+    // Create Full HTML format.
+    $full_html_format = entity_create('filter_format', array(
+      'format' => 'full_html',
+      'name' => 'Full HTML',
+      'weight' => 1,
+      'filters' => array(),
+    ));
+    $full_html_format->save();
+
+    // Create a user 1, which we don't want to use in our access-sensitive
+    // tests.
+    $this->createUser();
+  }
+
+  /**
+   * Checks that filter format access is respected on text fields.
+   */
+  public function testAccess() {
+    $entity = entity_create('entity_test', array('field_test_text' => array('value' => 'test', 'format' => 'filtered_html')));
+    $unpriviledged_user = $this->createUser(array(), array('administer entity_test content', 'use text format filtered_html'));
+    $priviledged_user = $this->createUser(array(), array('administer entity_test content', 'use text format filtered_html', 'use text format full_html'));
+
+    $this->assertTrue($entity->get('field_test_text')->access('create', $unpriviledged_user), 'Unpriviledged user is allowed to create field with filtered_html');
+    $this->assertTrue($entity->get('field_test_text')->access('create', $priviledged_user), 'Priviledged user is allowed to create field with filtered_html');
+
+    $this->assertTrue($entity->get('field_test_text')->access('update', $unpriviledged_user), 'Unpriviledged user is allowed to update field with filtered_html');
+    $this->assertTrue($entity->get('field_test_text')->access('update', $priviledged_user), 'Priviledged user is allowed to update field with filtered_html');
+
+    $entity->set('field_test_text', array('value' => 'test', 'format' => 'full_html'));
+    $this->assertFalse($entity->get('field_test_text')->access('create', $unpriviledged_user), 'Unpriviledged user is not allowed to create field with full_html');
+    $this->assertTrue($entity->get('field_test_text')->access('create', $priviledged_user), 'Priviledged user is allowed to create field with full_html');
+
+    $this->assertFalse($entity->get('field_test_text')->access('update', $unpriviledged_user), 'Unpriviledged user is not allowed to update field with full_html');
+    $this->assertTrue($entity->get('field_test_text')->access('update', $priviledged_user), 'Priviledged user is allowed to update field with full_html');
+  }
+
+}
diff --git a/core/modules/text/lib/Drupal/text/TextField.php b/core/modules/text/lib/Drupal/text/TextField.php
new file mode 100644
index 0000000..2f6bbe2
--- /dev/null
+++ b/core/modules/text/lib/Drupal/text/TextField.php
@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\text\TextField.
+ */
+
+namespace Drupal\text;
+
+use Drupal\Core\Session\AccountInterface;
+use Drupal\field\Plugin\Type\FieldType\ConfigField;
+
+/**
+ * Provides a text field class to deal with filter format access.
+ */
+class TextField extends ConfigField {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultAccess($operation = 'view', AccountInterface $account = NULL) {
+    if ($operation != 'create' && $operation != 'update') {
+      return;
+    }
+    if ($account == NULL) {
+      $account = \Drupal::request()->attributes->get('_account');
+    }
+    // Iterate over all field items, if one uses a not allowed format return
+    // FALSE immediately.
+    foreach ($this as $item) {
+      $format_name = $item->get('format')->getValue();
+      $format = filter_format_load($format_name);
+      if (!$format || !filter_access($format, $account)) {
+        return FALSE;
+      }
+    }
+    // All formats in all items are allowed for this user, so we can grant
+    // access.
+    return TRUE;
+  }
+
+}
