Simplified the login logic for the email fallback
authorAlexander Ebert <ebert@woltlab.com>
Tue, 17 Dec 2024 19:32:46 +0000 (20:32 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Tue, 17 Dec 2024 19:32:46 +0000 (20:32 +0100)
wcfsetup/install/files/lib/acp/form/LoginForm.class.php

index cfc495aa16a580166f1cb8cc9f30717bdce1d29a..8e2e23f8808ac54d4f3349f5701155bbe00f1b50 100755 (executable)
@@ -133,55 +133,56 @@ class LoginForm extends AbstractFormBuilderForm
     {
         $usernameFormField = $this->form->getNodeById('username');
         \assert($usernameFormField instanceof TextFormField);
-        $handleException = null;
+        $validationError = null;
 
         try {
             $this->user = UserAuthenticationFactory::getInstance()
                 ->getUserAuthentication()
                 ->loginManually($usernameFormField->getValue(), $passwordFormField->getValue());
         } catch (UserInputException $e) {
-            if (
-                \get_class(UserAuthenticationFactory::getInstance()->getUserAuthentication()) === DefaultUserAuthentication::class
-                && $e->getField() == 'username'
-            ) {
+            $validationError = $e;
+
+            if ($e->getField() === 'username') {
                 try {
-                    $this->user = EmailUserAuthentication::getInstance()
-                        ->loginManually($usernameFormField->getValue(), $passwordFormField->getValue());
-                } catch (UserInputException $e2) {
-                    if ($e2->getField() == 'username') {
-                        $handleException = $e;
-                    } else {
-                        $handleException = $e2;
+                    $user = $this->tryAuthenticationByEmail($usernameFormField->getValue(), $passwordFormField->getValue());
+                    if ($user !== null) {
+                        $this->user = $user;
+                        $validationError = null;
+                    }
+                } catch (UserInputException $emailException) {
+                    // The attempt to use the email address as login username is
+                    // only implicit, therefore we only use the inner exception
+                    // if the error is about an incorrect password.
+                    if ($emailException->getField() !== 'username') {
+                        $validationError = $emailException;
                     }
                 }
-            } else {
-                $handleException = $e;
             }
         }
 
-        if ($handleException !== null) {
-            if ($handleException->getField() == 'username') {
+        if ($validationError !== null) {
+            if ($validationError->getField() == 'username') {
                 $usernameFormField->addValidationError(
                     new FormFieldValidationError(
-                        $handleException->getType(),
-                        'wcf.user.username.error.' . $handleException->getType(),
+                        $validationError->getType(),
+                        'wcf.user.username.error.' . $validationError->getType(),
                         [
                             'username' => $usernameFormField->getValue(),
                         ]
                     )
                 );
-            } else if ($handleException->getField() == 'password') {
+            } else if ($validationError->getField() == 'password') {
                 $passwordFormField->addValidationError(
                     new FormFieldValidationError(
-                        $handleException->getType(),
-                        'wcf.user.password.error.' . $handleException->getType()
+                        $validationError->getType(),
+                        'wcf.user.password.error.' . $validationError->getType()
                     )
                 );
             } else {
                 throw new \LogicException('unreachable');
             }
 
-            $this->saveAuthenticationFailure($handleException->getField(), $usernameFormField->getValue());
+            $this->saveAuthenticationFailure($validationError->getField(), $usernameFormField->getValue());
         }
 
         if (RequestHandler::getInstance()->isACPRequest() && $this->user !== null) {
@@ -205,6 +206,20 @@ class LoginForm extends AbstractFormBuilderForm
         }
     }
 
+    protected function tryAuthenticationByEmail(
+        string $username,
+        #[\SensitiveParameter] string $password
+    ): ?User {
+        $defaultAuthentication = UserAuthenticationFactory::getInstance()->getUserAuthentication();
+        if (\get_class($defaultAuthentication) !== DefaultUserAuthentication::class) {
+            // The email fallback is only supported for the built-in
+            // authentication method.
+            return null;
+        }
+
+        return EmailUserAuthentication::getInstance()->loginManually($username, $password);
+    }
+
     protected function saveAuthenticationFailure(string $errorField, string $username): void
     {
         if (!ENABLE_USER_AUTHENTICATION_FAILURE) {