Repository: privacyidea/privacyidea

Issue:
Misleading log-message when admin login fails
When an admin login fails due to a missing `password` parameter or a wrong password, the result of the `/auth/` request is a correct `"Authentication failure. Wrong credentials"`. But the privacyIDEA log contains the warning `A user 'admin' exists as local admin and as user in your default realm!` which is wrong.
If a `realm` is missing in the request, we set it to the default realm:
https://github.com/privacyidea/privacyidea/blob/895c967935cccb111ce594063cc50cb2a69f1e56/privacyidea/api/auth.py#L236
The warning gets printed if the admin authentication fails and the realm is the default (which is always the case for an internal admin):
https://github.com/privacyidea/privacyidea/blob/895c967935cccb111ce594063cc50cb2a69f1e56/privacyidea/api/auth.py#L312



Discussion:
"Authentication failure. Wrong credentials" is OK, since we do not want to leak any further information.

So it looks like that we only need to fix the audit log.

[This](https://github.com/privacyidea/privacyidea/blob/895c967935cccb111ce594063cc50cb2a69f1e56/privacyidea/api/auth.py#L306) checks if the normal user from the realm successfully authenticates.
If not, the return value `user_auth`  is False.

The Line 312 is there to notify in the log, that there is a username clash between an admin and a user.

The problem is, that `check_webui_user` would return `False`, also if the user does not exist in the realm at all.

Thus this message is currently always written to the log file, if a local admin enters a wrong PW.

So I think the line 312 needs to be changed to 

~~~~python
if db_admin_exist(loginname) and user_auth and realm == get_default_realm():
~~~~ 

Resolving patch:
diff --git a/privacyidea/api/auth.py b/privacyidea/api/auth.py
--- a/privacyidea/api/auth.py
+++ b/privacyidea/api/auth.py
@@ -309,9 +309,11 @@ def get_auth_token():
                                                     superuser_realms=
                                                     superuser_realms)
         details = details or {}
-        if db_admin_exist(loginname) and realm == get_default_realm():
+        if db_admin_exist(loginname) and user_auth and realm == get_default_realm():
             # If there is a local admin with the same login name as the user
             # in the default realm, we inform about this in the log file.
+            # This condition can only be checked if the user was authenticated as it
+            # is the only way to verify if such a user exists.
             log.warning("A user '{0!s}' exists as local admin and as user in "
                         "your default realm!".format(loginname))
         if role == ROLE.ADMIN:


Test patch:
diff --git a/tests/test_api_auth.py b/tests/test_api_auth.py
--- a/tests/test_api_auth.py
+++ b/tests/test_api_auth.py
@@ -559,7 +559,7 @@ def test_04_remote_user_auth(self):
 class DuplicateUserApiTestCase(MyApiTestCase):
 
     def test_01_admin_and_user_same_name(self):
-        # Test the logging, if admin and user have the same name (testamdin/testpw)
+        # Test the logging, if admin and user have the same name (testadmin/testpw)
         # Now create a default realm, that contains the used "testadmin"
         rid = save_resolver({"resolver": self.resolvername1,
                              "type": "passwdresolver",
@@ -605,6 +605,22 @@ def test_01_admin_and_user_same_name(self):
             mock_log.assert_called_with("A user 'testadmin' exists as local admin and as user "
                                         "in your default realm!")
 
+        # Check that a wrong/missing password doesn't trigger the warning in the log
+        with mock.patch("logging.Logger.warning") as mock_log:
+            with self.app.test_request_context('/auth',
+                                               method='POST',
+                                               data={"username": "testadmin",
+                                                     "password": "unknown"}):
+                res = self.app.full_dispatch_request()
+                self.assertEqual(401, res.status_code, res)
+                result = res.json.get("result")
+                self.assertFalse(result.get("status"), result)
+                self.assertEqual(result.get("error").get('code'), 4031, result)
+                self.assertEqual(result.get("error").get('message'),
+                                 'Authentication failure. Wrong credentials', result)
+            # check if we have the correct log entry
+            mock_log.assert_called_with("user uid 1004 failed to authenticate")
+
 
 class AAPreEventHandlerTest(MyApiTestCase):