diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/PasswordWidget.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/PasswordWidget.php
new file mode 100644
index 0000000..7c6e79e
--- /dev/null
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/PasswordWidget.php
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Field\Plugin\Field\FieldWidget\PasswordWidget.
+ */
+
+namespace Drupal\Core\Field\Plugin\Field\FieldWidget;
+
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\WidgetBase;
+
+/**
+ * Plugin implementation of the 'password' widget.
+ *
+ * @FieldWidget(
+ *   id = "password",
+ *   label = @Translation("Password field"),
+ *   field_types = {
+ *     "string"
+ *   },
+ *   settings = {
+ *     "size" = ""
+ *   }
+ * )
+ */
+class PasswordWidget extends WidgetBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, array &$form_state) {
+    $element['value'] = $element + array(
+      '#type' => 'password_confirm',
+      '#size' => $this->getSetting('size'),
+    );
+    $element['value']['#description'] = $this->t('To change the current user password, enter the new password in both fields.');
+
+    return $element;
+  }
+}
diff --git a/core/modules/dblog/lib/Drupal/dblog/Tests/DbLogTest.php b/core/modules/dblog/lib/Drupal/dblog/Tests/DbLogTest.php
index 24add00..8612182 100644
--- a/core/modules/dblog/lib/Drupal/dblog/Tests/DbLogTest.php
+++ b/core/modules/dblog/lib/Drupal/dblog/Tests/DbLogTest.php
@@ -219,7 +219,7 @@ private function doUser() {
     // Add a user using the form to generate an add user event (which is not
     // triggered by drupalCreateUser).
     $edit = array();
-    $edit['name'] = $name;
+    $edit['name'][0]['value'] = $name;
     $edit['mail'] = $name . '@example.com';
     $edit['pass[pass1]'] = $pass;
     $edit['pass[pass2]'] = $pass;
diff --git a/core/modules/user/lib/Drupal/user/AccountFormController.php b/core/modules/user/lib/Drupal/user/AccountFormController.php
index ed4cc07..7c8ad79 100644
--- a/core/modules/user/lib/Drupal/user/AccountFormController.php
+++ b/core/modules/user/lib/Drupal/user/AccountFormController.php
@@ -69,6 +69,9 @@ public static function create(ContainerInterface $container) {
   public function form(array $form, array &$form_state) {
     /** @var \Drupal\user\UserInterface $account */
     $account = $this->entity;
+
+    $form = parent::form($form, $form_state, $account);
+
     $user = $this->currentUser();
     $config = \Drupal::config('user.settings');
 
@@ -83,39 +86,18 @@ public function form(array $form, array &$form_state) {
     );
 
     // Only show name field on registration form or user can change own username.
-    $form['account']['name'] = array(
-      '#type' => 'textfield',
-      '#title' => $this->t('Username'),
-      '#maxlength' => USERNAME_MAX_LENGTH,
-      '#description' => $this->t('Spaces are allowed; punctuation is not allowed except for periods, hyphens, apostrophes, and underscores.'),
-      '#required' => TRUE,
-      '#attributes' => array('class' => array('username'), 'autocorrect' => 'off', 'autocomplete' => 'off', 'autocapitalize' => 'off',
-      'spellcheck' => 'false'),
-      '#default_value' => (!$register ? $account->getUsername() : ''),
-      '#access' => ($register || ($user->id() == $account->id() && $user->hasPermission('change own username')) || $admin),
-      '#weight' => -10,
-    );
+    $form['account']['name'] = $form['name'];
+    unset($form['name']);
 
-    // The mail field is NOT required if account originally had no mail set
-    // and the user performing the edit has 'administer users' permission.
-    // This allows users without e-mail address to be edited and deleted.
-    $form['account']['mail'] = array(
-      '#type' => 'email',
-      '#title' => $this->t('E-mail address'),
-      '#description' => $this->t('A valid e-mail address. All e-mails from the system will be sent to this address. The e-mail address is not made public and will only be used if you wish to receive a new password or wish to receive certain news or notifications by e-mail.'),
-      '#required' => !(!$account->getEmail() && $user->hasPermission('administer users')),
-      '#default_value' => (!$register ? $account->getEmail() : ''),
-      '#attributes' => array('autocomplete' => 'off'),
-    );
+
+    $form['account']['mail'] = $form['mail'];
+    unset($form['mail']);
 
     // Display password field only for existing users or when user is allowed to
     // assign a password during registration.
     if (!$register) {
-      $form['account']['pass'] = array(
-        '#type' => 'password_confirm',
-        '#size' => 25,
-        '#description' => $this->t('To change the current user password, enter the new password in both fields.'),
-      );
+      $form['account']['pass'] = $form['pass'];
+      unset($form['pass']);
 
       // To skip the current password field, the user must have logged in via a
       // one-time link and have the token in the URL.
@@ -127,7 +109,7 @@ public function form(array $form, array &$form_state) {
       // The user may only change their own password without their current
       // password if they logged in via a one-time login link.
       if (!$pass_reset) {
-        $protected_values['mail'] = $form['account']['mail']['#title'];
+        $protected_values['mail'] = $this->t('E-mail address');
         $protected_values['pass'] = $this->t('Password');
         $request_new = l($this->t('Request new password'), 'user/password', array('attributes' => array('title' => $this->t('Request new password via e-mail.'))));
         $current_pass_description = $this->t('Required if you want to change the %mail or %pass below. !request_new.', array('%mail' => $protected_values['mail'], '%pass' => $protected_values['pass'], '!request_new' => $request_new));
@@ -290,7 +272,7 @@ public function form(array $form, array &$form_state) {
       '#weight' => 100,
     );
 
-    return parent::form($form, $form_state, $account);
+    return $form;
   }
 
   /**
diff --git a/core/modules/user/lib/Drupal/user/Entity/User.php b/core/modules/user/lib/Drupal/user/Entity/User.php
index 8cac65c..5c0d548 100644
--- a/core/modules/user/lib/Drupal/user/Entity/User.php
+++ b/core/modules/user/lib/Drupal/user/Entity/User.php
@@ -433,14 +433,17 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
       ->setDescription(t('The user UUID.'))
       ->setReadOnly(TRUE);
 
+    // @todo Use LanguageWidget once https://drupal.org/node/2226493 lands.
     $fields['langcode'] = FieldDefinition::create('language')
       ->setLabel(t('Language code'))
       ->setDescription(t('The user language code.'));
 
+    // @todo Use LanguageWidget once https://drupal.org/node/2226493 lands.
     $fields['preferred_langcode'] = FieldDefinition::create('language')
       ->setLabel(t('Preferred admin language code'))
       ->setDescription(t("The user's preferred language code for receiving emails and viewing the site."));
 
+    // @todo Use LanguageWidget once https://drupal.org/node/2226493 lands.
     $fields['preferred_admin_langcode'] = FieldDefinition::create('language')
       ->setLabel(t('Preferred language code'))
       ->setDescription(t("The user's preferred language code for viewing administration pages."));
@@ -448,25 +451,45 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
     // The name should not vary per language. The username is the visual
     // identifier for a user and needs to be consistent in all languages.
     $fields['name'] = FieldDefinition::create('string')
-      ->setLabel(t('Name'))
+      ->setLabel(t('Username'))
       ->setDescription(t('The name of this user.'))
-      ->setSetting('default_value', '')
+      ->setRequired(TRUE)
+      ->setSettings(array(
+        'default_value' => '',
+        'max_length' => USERNAME_MAX_LENGTH,
+      ))
       ->setPropertyConstraints('value', array(
         // No Length constraint here because the UserName constraint also covers
         // that.
         'UserName' => array(),
         'UserNameUnique' => array(),
+      ))
+      ->setDisplayOptions('form', array(
+        'type' => 'username',
+        'weight' => -20,
       ));
 
     $fields['pass'] = FieldDefinition::create('string')
       ->setLabel(t('Password'))
-      ->setDescription(t('The password of this user (hashed).'));
+      ->setDescription(t('The password of this user (hashed).'))
+      ->setDisplayOptions('form', array(
+        'type' => 'password',
+        'weight' => 0,
+        'settings' => array(
+          'size' => 25,
+        ),
+      ));
 
     $fields['mail'] = FieldDefinition::create('email')
-      ->setLabel(t('Email'))
+      ->setLabel(t('E-mail address'))
       ->setDescription(t('The email of this user.'))
       ->setSetting('default_value', '')
-      ->setPropertyConstraints('value', array('UserMailUnique' => array()));
+      ->setPropertyConstraints('value', array('UserMailUnique' => array()))
+      ->setDisplayOptions('form', array(
+        'type' => 'email_user',
+        'weight' => -10,
+      ))
+      ->setDisplayConfigurable('form', TRUE);
 
     // @todo Convert to a text field in https://drupal.org/node/1548204.
     $fields['signature'] = FieldDefinition::create('string')
diff --git a/core/modules/user/lib/Drupal/user/Plugin/Field/FieldWidget/EmailUserWidget.php b/core/modules/user/lib/Drupal/user/Plugin/Field/FieldWidget/EmailUserWidget.php
new file mode 100644
index 0000000..5e3e69b
--- /dev/null
+++ b/core/modules/user/lib/Drupal/user/Plugin/Field/FieldWidget/EmailUserWidget.php
@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\user\Plugin\Field\FieldWidget\EmailUserWidget.
+ */
+
+namespace Drupal\user\Plugin\Field\FieldWidget;
+
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\WidgetBase;
+
+/**
+ * Plugin implementation of the 'email_user' widget.
+ *
+ * @FieldWidget(
+ *   id = "email_user",
+ *   label = @Translation("User e-mail"),
+ *   field_types = {
+ *     "email"
+ *   }
+ * )
+ */
+class EmailUserWidget extends WidgetBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, array &$form_state) {
+    $account = $element['#entity'];
+    $user = \Drupal::currentUser();
+
+    $element['value'] = $element + array(
+      '#type' => 'email',
+      '#description' => $this->t('A valid e-mail address. All e-mails from the system will be sent to this address. The e-mail address is not made public and will only be used if you wish to receive a new password or wish to receive certain news or notifications by e-mail.'),
+      // The mail field is NOT required if account originally had no mail set
+      // and the user performing the edit has 'administer users' permission.
+      // This allows users without e-mail address to be edited and deleted.
+      '#required' => !(!$account->getEmail() && $user->hasPermission('administer users')),
+      '#default_value' => (!$account->isAnonymous() ? $account->getEmail() : ''),
+      '#attributes' => array('autocomplete' => 'off'),
+    );
+
+    return $element;
+  }
+
+}
diff --git a/core/modules/user/lib/Drupal/user/Plugin/Field/FieldWidget/UserNameWidget.php b/core/modules/user/lib/Drupal/user/Plugin/Field/FieldWidget/UserNameWidget.php
new file mode 100644
index 0000000..d7798be
--- /dev/null
+++ b/core/modules/user/lib/Drupal/user/Plugin/Field/FieldWidget/UserNameWidget.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Field\Plugin\Field\FieldWidget\StringWidget.
+ */
+
+namespace Drupal\user\Plugin\Field\FieldWidget;
+
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\WidgetBase;
+
+/**
+ * Plugin implementation of the 'user name' widget.
+ *
+ * @FieldWidget(
+ *   id = "username",
+ *   label = @Translation("User name field"),
+ *   field_types = {
+ *     "string"
+ *   }
+ * )
+ */
+class UserNameWidget extends WidgetBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, array &$form_state) {
+    $account = $element['#entity'];
+    $user = \Drupal::currentUser();
+
+    $is_anon = $account->isAnonymous();
+    $is_admin = $user->hasPermission('administer users');;
+
+    $element['value'] = $element + array(
+      '#type' => 'textfield',
+      '#default_value' => isset($items[$delta]->value) ? $items[$delta]->value : NULL,
+      '#size' => $this->getSetting('size'),
+      '#maxlength' => $this->getFieldSetting('max_length'),
+      '#attributes' => array(
+        'class' => array('username'),
+        'autocorrect' => 'off',
+        'autocomplete' => 'off',
+        'autocapitalize' => 'off',
+        'spellcheck' => 'false',
+      ),
+      '#default_value' => (!$is_anon ? $account->getUsername() : ''),
+      // Only show name field on registration form or user can change own
+      // username.
+      '#access' => ($is_anon || ($user->id() == $account->id() && $user->hasPermission('change own username')) || $is_admin),
+    );
+    $element['value']['#description'] = $this->t('Spaces are allowed; punctuation is not allowed except for periods, hyphens, apostrophes, and underscores.');
+
+    return $element;
+  }
+
+}
