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
This commit is contained in:
gorkem-bwl committed 2025-08-12 21:09:14 -04:00
1 parent f2e2d5c2ed
commit a03996d54b
2 files changed
+23 -17

No files matched your search

+22 -16
View File
@@ -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) => {
@@ -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() {