diff --git a/core/modules/rest/src/Annotation/RestResource.php b/core/modules/rest/src/Annotation/RestResource.php
index e63f07d..947e3dd 100644
--- a/core/modules/rest/src/Annotation/RestResource.php
+++ b/core/modules/rest/src/Annotation/RestResource.php
@@ -43,4 +43,11 @@ class RestResource extends Plugin {
    */
   public $label;
 
+  /**
+   * Options available.
+   *
+   * @var array
+   */
+  public $serialization_context;
+
 }
diff --git a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
index b7d0264..03555b2 100644
--- a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
+++ b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
@@ -89,7 +89,7 @@ public function post(EntityInterface $entity = NULL) {
     }
     foreach ($entity as $field_name => $field) {
       if (!$field->access('create')) {
-        throw new AccessDeniedHttpException(String::format('Access denied on creating field ', array('@field' => $field_name)));
+        throw new AccessDeniedHttpException(String::format('Access denied on creating field @field', array('@field' => $field_name)));
       }
     }
 
diff --git a/core/modules/rest/src/Plugin/rest/resource/UserRegistrationResource.php b/core/modules/rest/src/Plugin/rest/resource/UserRegistrationResource.php
new file mode 100644
index 0000000..db6ea19
--- /dev/null
+++ b/core/modules/rest/src/Plugin/rest/resource/UserRegistrationResource.php
@@ -0,0 +1,130 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\rest\Plugin\rest\resource\UserRegistrationResource.
+ */
+
+namespace Drupal\rest\Plugin\rest\resource;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\rest\ResourceResponse;
+use Symfony\Component\Routing\RouteCollection;
+use Drupal\Component\Utility\String;
+use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
+use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
+
+/**
+ * Represents user registration as resource.
+ *
+ * @RestResource(
+ *   id = "rest_user_registration",
+ *   label = @Translation("User Registration"),
+ *   serialization_class = "Drupal\Core\Entity\Entity",
+ *   serialization_context = {
+ *     "entity_type" = "user"
+ *   }
+ * )
+ *
+ * @see \Drupal\rest\Plugin\Derivative\EntityDerivative
+ */
+class UserRegistrationResource extends EntityResource {
+
+  /**
+   * Responds to entity POST requests and saves the new entity.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity.
+   *
+   * @return \Drupal\rest\ResourceResponse
+   *   The HTTP response object.
+   *
+   * @throws \Symfony\Component\HttpKernel\Exception\HttpException
+   */
+  public function post(EntityInterface $entity = NULL) {
+
+    if ($entity == NULL) {
+      throw new BadRequestHttpException('No entity content received.');
+    }
+
+    $definition = $this->getPluginDefinition();
+    // Verify that the deserialized entity is of the type that we expect to
+    // prevent security issues.
+    if ($entity->getEntityTypeId() != $definition['serialization_context']['entity_type']) {
+      throw new BadRequestHttpException('Invalid entity type');
+    }
+    // POSTed entities must not have an ID set, because we always want to create
+    // new entities here.
+    if (!$entity->isNew()) {
+      throw new BadRequestHttpException('Only new entities can be created');
+    }
+
+    $approvalSettings = \Drupal::config('user.settings')->get('register');
+    // Verify that the current user can register a user account.
+    if ($approvalSettings == 'admin_only') {
+      throw new AccessDeniedHttpException('Only administrators can register users.');
+    }
+    // If current user can register accounts then let's block the new registered user if admin approval is needed.
+    elseif ($approvalSettings == 'visitors_admin_approval') {
+      $entity->block();
+    }
+
+    // Username and email cannot exist.
+    $this->validate($entity);
+
+    // Cannot add extra roles.
+    $roles = $entity->getRoles();
+    foreach ($roles as $role) {
+      if ($role != 'authenticated' && $role != 'anonymous') {
+        throw new BadRequestHttpException(String::format('Anonymous user cannot assign roles when registering a new user account and by default' .
+          ' authenticated is added, so you cannot assign @role role.', array('@role' => $role)));
+      }
+    }
+
+    $entity->save();
+
+    // "Verify email" option disabled and the account as active means that the user can be logged in now.
+    if (!\Drupal::config('user.settings')->get('verify_mail') && $entity->isActive()) {
+      _user_mail_notify('register_no_approval_required', $entity);
+      user_login_finalize($entity);
+    }
+    // The new account as blocked means that it needs approval.
+    elseif (!$entity->isActive()) {
+      _user_mail_notify('register_pending_approval', $entity);
+    }
+
+    return new ResourceResponse(NULL, 201);
+
+  }
+
+  /**
+   * Implements ResourceInterface::routes().
+   */
+  public function routes() {
+    $collection = new RouteCollection();
+
+    $route_name = strtr($this->pluginId, ':', '.');
+
+    $methods = $this->availableMethods();
+    foreach ($methods as $method) {
+      $route = $this->getBaseRoute('/entity/user/register', $method);
+
+      switch ($method) {
+        case 'POST':
+          $route->setPattern('/entity/user/register');
+          // Restrict the incoming HTTP Content-type header to the known
+          // serialization formats.
+          $route->addRequirements(array('_content_type_format' => implode('|', $this->serializerFormats)));
+          $collection->add("$route_name.$method", $route);
+          break;
+
+        default:
+          $collection->add("$route_name.$method", $route);
+          break;
+      }
+    }
+
+    return $collection;
+  }
+
+}
\ No newline at end of file
diff --git a/core/modules/rest/src/RequestHandler.php b/core/modules/rest/src/RequestHandler.php
index c31600d..d48fe03 100644
--- a/core/modules/rest/src/RequestHandler.php
+++ b/core/modules/rest/src/RequestHandler.php
@@ -60,8 +60,17 @@ public function handle(RouteMatchInterface $route_match, Request $request) {
       if (empty($method_settings['supported_formats']) || in_array($format, $method_settings['supported_formats'])) {
         $definition = $resource->getPluginDefinition();
         $class = $definition['serialization_class'];
+        $context = array();
+        // Get context information for deserialization from the plugin
+        // definition.
+        if (!empty($definition['serialization_context'])) {
+          $context = $definition['serialization_context'];
+        }
+        // Always add the resource ID to the deserialization context.
+        $context['resource_id'] = $plugin;
+        $context['request_method'] = $method;
         try {
-          $unserialized = $serializer->deserialize($received, $class, $format, array('request_method' => $method));
+          $unserialized = $serializer->deserialize($received, $class, $format, $context);
         }
         catch (UnexpectedValueException $e) {
           $error['error'] = $e->getMessage();
diff --git a/core/modules/serialization/src/Normalizer/EntityNormalizer.php b/core/modules/serialization/src/Normalizer/EntityNormalizer.php
index 5e81b5a..be2abc8 100644
--- a/core/modules/serialization/src/Normalizer/EntityNormalizer.php
+++ b/core/modules/serialization/src/Normalizer/EntityNormalizer.php
@@ -45,7 +45,7 @@ public function __construct(EntityManagerInterface $entity_manager) {
    */
   public function denormalize($data, $class, $format = NULL, array $context = array()) {
     if (empty($context['entity_type'])) {
-      throw new UnexpectedValueException('Entity type parameter must be included in context.');
+      throw new UnexpectedValueException('Entity type parameter must be included in context.' . print_r($context, TRUE));
     }
 
     $entity_type = $this->entityManager->getDefinition($context['entity_type']);
