From a03996d54b8e487a3433cd231bd842ab03c0b0c1 Mon Sep 17 00:00:00 2001 From: gorkem-bwl Date: Tue, 12 Aug 2025 21:09:14 -0400 Subject: [PATCH] fix: resolve login error handling issues - Fix translation service to load locales from correct path (src/locales) - Improve login security to return generic error message for both invalid email and wrong password - Make frontend error handling generic to display backend error messages properly - Remove hardcoded string matching in favor of HTTP status code checks Fixes login flow returning raw localization keys instead of user-facing messages Fixes #2768 --- server/src/service/business/userService.js | 38 +++++++++++-------- .../src/service/system/translationService.js | 2 +- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/server/src/service/business/userService.js b/server/src/service/business/userService.js index 0a965bced..e69796ec4 100644 --- a/server/src/service/business/userService.js +++ b/server/src/service/business/userService.js @@ -83,24 +83,30 @@ class UserService { loginUser = async (email, password) => { // Check if user exists - const user = await this.db.userModule.getUserByEmail(email); - // Compare password - const match = await user.comparePassword(password); - if (match !== true) { + try { + const user = await this.db.userModule.getUserByEmail(email); + // Compare password + const match = await user.comparePassword(password); + if (match !== true) { + throw this.errorService.createAuthenticationError(this.stringService.authIncorrectPassword); + } + + // Remove password from user object. Should this be abstracted to DB layer? + const userWithoutPassword = { ...user._doc }; + delete userWithoutPassword.password; + delete userWithoutPassword.avatarImage; + + // Happy path, return token + const appSettings = await this.settingsService.getSettings(); + const token = this.issueToken(userWithoutPassword, appSettings); + // reset avatar image + userWithoutPassword.avatarImage = user.avatarImage; + return { user: userWithoutPassword, token }; + } catch (error) { + // If user is not found, throw a generic authentication error for security + // Don't reveal whether user exists or password is wrong throw this.errorService.createAuthenticationError(this.stringService.authIncorrectPassword); } - - // Remove password from user object. Should this be abstracted to DB layer? - const userWithoutPassword = { ...user._doc }; - delete userWithoutPassword.password; - delete userWithoutPassword.avatarImage; - - // Happy path, return token - const appSettings = await this.settingsService.getSettings(); - const token = this.issueToken(userWithoutPassword, appSettings); - // reset avatar image - userWithoutPassword.avatarImage = user.avatarImage; - return { user: userWithoutPassword, token }; }; editUser = async (updates, file, currentUser) => { diff --git a/server/src/service/system/translationService.js b/server/src/service/system/translationService.js index 20b3431e0..2f4d66df0 100755 --- a/server/src/service/system/translationService.js +++ b/server/src/service/system/translationService.js @@ -7,7 +7,7 @@ class TranslationService { this.logger = logger; this.translations = {}; this._language = "en"; - this.localesDir = path.join(process.cwd(), "locales"); + this.localesDir = path.join(process.cwd(), "src", "locales"); } get serviceName() {