GUACAMOLE-1289: Ensure updates to credentials are accurately represented in failure events.
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/auth/AuthenticationService.java b/guacamole/src/main/java/org/apache/guacamole/rest/auth/AuthenticationService.java
index 7bb1e6f..5a0e4c5 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/auth/AuthenticationService.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/auth/AuthenticationService.java
@@ -333,43 +333,6 @@
     }
 
     /**
-     * Performs arbitrary and optional updates to the credentials supplied by
-     * the authenticating user as dictated by the {@link AuthenticationProvider#updateCredentials(org.apache.guacamole.net.auth.Credentials)}
-     * functions of any installed AuthenticationProvider. Each installed
-     * AuthenticationProvider is given the opportunity, in order, to make
-     * updates to the supplied credentials.
-     *
-     * @param credentials
-     *     The credentials to be updated.
-     *
-     * @return
-     *     The set of credentials that should be provided to all
-     *     AuthenticationProviders during authentication, now possibly updated
-     *     (or even replaced) by any number of installed
-     *     AuthenticationProviders.
-     *
-     * @throws GuacamoleAuthenticationProcessException 
-     *     If an error occurs while updating the supplied credentials.
-     */
-    private Credentials getUpdatedCredentials(Credentials credentials)
-            throws GuacamoleAuthenticationProcessException {
-
-        for (AuthenticationProvider authProvider : authProviders) {
-            try {
-                credentials = authProvider.updateCredentials(credentials);
-            }
-            catch (GuacamoleException | RuntimeException | Error e) {
-                throw new GuacamoleAuthenticationProcessException("User "
-                        + "authentication aborted during credential "
-                        + "update/revision.", authProvider, e);
-            }
-        }
-
-        return credentials;
-
-    }
-
-    /**
      * Authenticates a user using the given credentials and optional
      * authentication token, returning the authentication token associated with
      * the user's Guacamole session, which may be newly generated. If an
@@ -394,27 +357,38 @@
     public String authenticate(Credentials credentials, String token)
             throws GuacamoleException {
 
-        // Fire pre-authentication event before ANY authn/authz occurs at all
-        listenerService.handleEvent((AuthenticationRequestReceivedEvent) () -> credentials);
-
-        // Pull existing session if token provided
-        GuacamoleSession existingSession;
-        if (token != null)
-            existingSession = tokenSessionMap.get(token);
-        else
-            existingSession = null;
-
-        AuthenticatedUser authenticatedUser;
         String authToken;
-
         try {
 
             // Allow extensions to make updated to credentials prior to
-            // actual authentication
-            Credentials updatedCredentials = getUpdatedCredentials(credentials);
+            // actual authentication (NOTE: We do this here instead of in a
+            // separate function to ensure that failure events accurately
+            // represent the credentials that failed when a chain of credential
+            // updates is involved)
+            for (AuthenticationProvider authProvider : authProviders) {
+                try {
+                    credentials = authProvider.updateCredentials(credentials);
+                }
+                catch (GuacamoleException | RuntimeException | Error e) {
+                    throw new GuacamoleAuthenticationProcessException("User "
+                            + "authentication aborted during credential "
+                            + "update/revision.", authProvider, e);
+                }
+            }
+
+            // Fire pre-authentication event before ANY authn/authz occurs at all
+            final Credentials updatedCredentials = credentials;
+            listenerService.handleEvent((AuthenticationRequestReceivedEvent) () -> updatedCredentials);
+
+            // Pull existing session if token provided
+            GuacamoleSession existingSession;
+            if (token != null)
+                existingSession = tokenSessionMap.get(token);
+            else
+                existingSession = null;
 
             // Get up-to-date AuthenticatedUser and associated UserContexts
-            authenticatedUser = getAuthenticatedUser(existingSession, updatedCredentials);
+            AuthenticatedUser authenticatedUser = getAuthenticatedUser(existingSession, updatedCredentials);
             List<DecoratedUserContext> userContexts = getUserContexts(existingSession, authenticatedUser, updatedCredentials);
 
             // Update existing session, if it exists
@@ -445,6 +419,11 @@
         // Log and rethrow any authentication errors
         catch (GuacamoleAuthenticationProcessException e) {
 
+            // NOTE: The credentials referenced here are intentionally NOT the
+            // final updatedCredentials reference (though they may often be
+            // equivalent) to ensure that failure events accurately represent
+            // the credentials that failed if that failure occurs in the middle
+            // of a chain of credential updates via updateCredentials()
             listenerService.handleEvent(new AuthenticationFailureEvent(credentials,
                     e.getAuthenticationProvider(), e.getCause()));