diff --git a/changelogs/unreleased/ghs_16_user_enumeration.md b/changelogs/unreleased/ghs_16_user_enumeration.md
new file mode 100644
index 0000000000000000000000000000000000000000..f22ebf08a2346e63d4fca1371add63e5ae49b785
--- /dev/null
+++ b/changelogs/unreleased/ghs_16_user_enumeration.md
@@ -0,0 +1,4 @@
+## bugfix/core
+
+* Now the same error is returned when invalid password or login is entered
+  during authorization to prevent user enumeration (ghs-16).
diff --git a/src/box/applier.cc b/src/box/applier.cc
index 053e4d4ded055d8424e4d02be591367674c97b14..de5ffd695171466d035944c072d39981b3d56fec 100644
--- a/src/box/applier.cc
+++ b/src/box/applier.cc
@@ -123,7 +123,7 @@ applier_log_error(struct applier *applier, struct error *e)
 	case ER_SYSTEM:
 	case ER_SSL:
 	case ER_UNKNOWN_REPLICA:
-	case ER_PASSWORD_MISMATCH:
+	case ER_CREDS_MISMATCH:
 	case ER_XLOG_GAP:
 	case ER_TOO_EARLY_SUBSCRIBE:
 	case ER_SYNC_QUORUM_TIMEOUT:
@@ -2203,7 +2203,7 @@ applier_f(va_list ap)
 			} else if (e->errcode() == ER_CFG ||
 				   e->errcode() == ER_ACCESS_DENIED ||
 				   e->errcode() == ER_NO_SUCH_USER ||
-				   e->errcode() == ER_PASSWORD_MISMATCH) {
+				   e->errcode() == ER_CREDS_MISMATCH) {
 				/* Invalid configuration */
 				applier_log_error(applier, e);
 				applier_disconnect(applier, APPLIER_LOADING);
diff --git a/src/box/authentication.cc b/src/box/authentication.cc
index 2c8109f1f50b9ec43c07d56aa4effc677058bb1c..c74fd91fb080ac76fa3d67c7fe308da955e3c903 100644
--- a/src/box/authentication.cc
+++ b/src/box/authentication.cc
@@ -41,7 +41,14 @@ void
 authenticate(const char *user_name, uint32_t len, const char *salt,
 	     const char *tuple)
 {
-	struct user *user = user_find_by_name_xc(user_name, len);
+	struct user *user = user_find_by_name(user_name, len);
+	if (user == NULL) {
+		if (diag_get()->last->code == ER_NO_SUCH_USER) {
+			diag_clear(diag_get());
+			diag_set(ClientError, ER_CREDS_MISMATCH);
+		}
+		diag_raise();
+	}
 	struct session *session = current_session();
 	uint32_t part_count;
 	uint32_t scramble_len;
@@ -93,7 +100,7 @@ authenticate(const char *user_name, uint32_t len, const char *salt,
 		auth_res.is_authenticated = false;
 		if (session_run_on_auth_triggers(&auth_res) != 0)
 			diag_raise();
-		tnt_raise(ClientError, ER_PASSWORD_MISMATCH, user->def->name);
+		tnt_raise(ClientError, ER_CREDS_MISMATCH);
 	}
 ok:
 	/* check and run auth triggers on success */
diff --git a/src/box/errcode.h b/src/box/errcode.h
index 4807745830d4aab32960db19c443408558dd4f57..c88892f485c5c029b49290cebae1f463434c3282 100644
--- a/src/box/errcode.h
+++ b/src/box/errcode.h
@@ -99,7 +99,7 @@ struct errcode_record {
 	/* 44 */_(ER_DROP_USER,			"Failed to drop user or role '%s': %s") \
 	/* 45 */_(ER_NO_SUCH_USER,		"User '%s' is not found") \
 	/* 46 */_(ER_USER_EXISTS,		"User '%s' already exists") \
-	/* 47 */_(ER_PASSWORD_MISMATCH,		"Incorrect password supplied for user '%s'") \
+	/* 47 */_(ER_CREDS_MISMATCH,		"User not found or supplied credentials are invalid") \
 	/* 48 */_(ER_UNKNOWN_REQUEST_TYPE,	"Unknown request type %u") \
 	/* 49 */_(ER_UNKNOWN_SCHEMA_OBJECT,	"Unknown object type '%s'") \
 	/* 50 */_(ER_CREATE_FUNCTION,		"Failed to create function '%s': %s") \
diff --git a/test/box-luatest/ghs_16_user_enumeration_test.lua b/test/box-luatest/ghs_16_user_enumeration_test.lua
new file mode 100644
index 0000000000000000000000000000000000000000..b822ea58854173cd14500f10b069c6f13085cdc7
--- /dev/null
+++ b/test/box-luatest/ghs_16_user_enumeration_test.lua
@@ -0,0 +1,33 @@
+local net = require('net.box')
+local server = require('test.luatest_helpers.server')
+local urilib = require('uri')
+local t = require('luatest')
+local g = t.group()
+
+g.before_all = function()
+    g.server = server:new({alias = 'master'})
+    g.server:start()
+    g.server:exec(function()
+        box.schema.user.create('test', {password = '1111'})
+    end)
+end
+
+g.after_all = function()
+    g.server:stop()
+end
+
+-- If we raise different errors in case of entering an invalid password and
+-- entering the login of a non-existent user during authorization, it will
+-- open the door for an unauthorized person to enumerate users.
+-- So raised errors must be the same in the cases described above.
+g.test_user_enum_on_auth = function()
+    local uri = urilib.parse(g.server.net_box_uri)
+    local err_msg = 'User not found or supplied credentials are invalid'
+    local cmd = 'return box.session.info()'
+    local c = net.connect('test:1112@' .. uri.unix)
+    t.assert_error_msg_contains(err_msg, c.eval , c, cmd)
+    c:close()
+    c = net.connect('nobody:1112@' .. uri.unix)
+    t.assert_error_msg_contains(err_msg, c.eval , c, cmd)
+    c:close()
+end
diff --git a/test/box/error.result b/test/box/error.result
index ba7bc0b5b8b23cd12bdfa091713060b248a24525..d162cfd26440a509d34462212f4a16241fc95cd8 100644
--- a/test/box/error.result
+++ b/test/box/error.result
@@ -267,7 +267,7 @@ t;
  |   44: box.error.DROP_USER
  |   45: box.error.NO_SUCH_USER
  |   46: box.error.USER_EXISTS
- |   47: box.error.PASSWORD_MISMATCH
+ |   47: box.error.CREDS_MISMATCH
  |   48: box.error.UNKNOWN_REQUEST_TYPE
  |   49: box.error.UNKNOWN_SCHEMA_OBJECT
  |   50: box.error.CREATE_FUNCTION
diff --git a/test/box/net.box_incorrect_iterator_gh-841.result b/test/box/net.box_incorrect_iterator_gh-841.result
index 498d8b691a42f3995db2c2474f5d17e0454be98e..43e42cac65deb629091a04bca16a87b91878b074 100644
--- a/test/box/net.box_incorrect_iterator_gh-841.result
+++ b/test/box/net.box_incorrect_iterator_gh-841.result
@@ -492,7 +492,7 @@ cn:is_connected()
 ...
 cn.error
 ---
-- User 'netbox' is not found
+- User not found or supplied credentials are invalid
 ...
 cn.state
 ---
diff --git a/test/box/net.box_uri_first_arg_gh-398.result b/test/box/net.box_uri_first_arg_gh-398.result
index 2caf8f7987501480f9d861e2cea88ca19a010ea6..bbf651dbf94f9c5c3d5866979872d65c1b43146a 100644
--- a/test/box/net.box_uri_first_arg_gh-398.result
+++ b/test/box/net.box_uri_first_arg_gh-398.result
@@ -31,7 +31,7 @@ cn ~= nil, cn.state, cn.error
 ---
 - true
 - error
-- Incorrect password supplied for user 'netbox'
+- User not found or supplied credentials are invalid
 ...
 cn:close()
 ---