GUACAMOLE-1152: Ensure field values accurately represent login state.

If expected fields are deleted rather than reset to empty, those fields
will not be resubmitted in future requests, resulting in the content of
those requests not accurately representing true client-side login state.

For example, if a user receives an insufficient credentials error due to
their password expiring, failing to provide any new password should
result in at least the following fields:

 1. Their original username (part of the initial login attempt)
 2. Their original password (part of the initial login attempt)
 3. Their new password (empty)

If fields are incorrectly reset to null, those fields will not be
submitted, resulting instead in a request containing only:

 1. Their original username (part of the initial login attempt)
 2. Their original password (part of the initial login attempt)

which is indistinguishable from a normal login attempt.
diff --git a/guacamole/src/main/webapp/app/login/directives/login.js b/guacamole/src/main/webapp/app/login/directives/login.js
index a414548..b7967d7 100644
--- a/guacamole/src/main/webapp/app/login/directives/login.js
+++ b/guacamole/src/main/webapp/app/login/directives/login.js
@@ -72,6 +72,23 @@
         var requestService        = $injector.get('requestService');
 
         /**
+         * The initial value for all login fields. Note that this value must
+         * not be null. If null, empty fields may not be submitted back to the
+         * server at all, causing the request to misrepresent true login state.
+         *
+         * For example, if a user receives an insufficient credentials error
+         * due to their password expiring, failing to provide that new password
+         * should result in the user submitting their username, original
+         * password, and empty new password. If only the username and original
+         * password are sent, the invalid password reset request will be
+         * indistinguishable from a normal login attempt.
+         *
+         * @constant
+         * @type String
+         */
+        var DEFAULT_FIELD_VALUE = '';
+
+        /**
          * A description of the error that occurred during login, if any.
          *
          * @type TranslatableMessage
@@ -148,7 +165,7 @@
             // Set default values for all unset fields
             angular.forEach($scope.remainingFields, function setDefault(field) {
                 if (!$scope.enteredValues[field.name])
-                    $scope.enteredValues[field.name] = '';
+                    $scope.enteredValues[field.name] = DEFAULT_FIELD_VALUE;
             });
 
             $scope.relevantField = getRelevantField();
@@ -195,13 +212,11 @@
                     else
                         $scope.loginError = error.translatableMessage;
 
-                    // Clear all remaining fields that are not username fields
+                    // Reset all remaining fields to default values, but
+                    // preserve any usernames
                     angular.forEach($scope.remainingFields, function clearEnteredValueIfPassword(field) {
-
-                        // If field is not username field, delete it.
                         if (field.type !== Field.Type.USERNAME && field.name in $scope.enteredValues)
-                            delete $scope.enteredValues[field.name];
-
+                            $scope.enteredValues[field.name] = DEFAULT_FIELD_VALUE;
                     });
                 }