Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 78 additions & 55 deletions backend/src/controllers/authController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,76 +15,95 @@ const generateToken = (id: string) => {
// @route POST /api/users
// @access Public
export const registerUser = async (req: Request, res: Response) => {
const { name, email, password } = req.body;
try {
const { name, email, password } = req.body;

if (!name || !email || !password) {
res.status(400).json({ message: 'Please add all fields' });
return;
}
if (!name || !email || !password) {
res.status(400).json({ message: 'Please add all fields' });
return;
}

const userExists = await prisma.user.findUnique({ where: { email } });
const userExists = await prisma.user.findUnique({ where: { email } });

if (userExists) {
res.status(400).json({ message: 'User already exists' });
return;
}
if (userExists) {
res.status(400).json({ message: 'User already exists' });
return;
}

const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);

const user = await prisma.user.create({
data: {
name,
email,
password: hashedPassword
const user = await prisma.user.create({
data: {
name,
email,
password: hashedPassword
}
});

if (user) {
res.status(201).json({
_id: user.id,
name: user.name,
email: user.email,
role: user.role,
token: generateToken(user.id),
xp_points: user.xp_points,
streak_days: user.streak_days,
solvedProblems: user.solvedProblems,
bookmarks: user.bookmarks,
activityLog: user.activityLog
});
} else {
res.status(400).json({ message: 'Invalid user data' });
}
});
}
catch (error: any) {
console.error('Register Error:', error);

if (user) {
res.status(201).json({
_id: user.id,
name: user.name,
email: user.email,
role: user.role,
token: generateToken(user.id),
xp_points: user.xp_points,
streak_days: user.streak_days,
solvedProblems: user.solvedProblems,
bookmarks: user.bookmarks,
activityLog: user.activityLog
res.status(500).json({
success: false,
message: error.message ||'Internal server error'
});
Comment on lines +64 to 67

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not return raw exception messages in auth 500 responses (Line 66, Line 105).

Both catch blocks currently expose error.message to clients, which can leak internal implementation details and conflicts with the PR’s “no internal error details” requirement. Return a fixed generic message to clients and keep detailed error info only in server logs.

Suggested patch
-        res.status(500).json({
-            success: false,
-            message: error.message ||'Internal server error'
-        });
+        res.status(500).json({
+            success: false,
+            message: 'Internal server error'
+        });
@@
-        res.status(500).json({
-            success: false,
-            message: error.message || 'Internal server error'
-        });
+        res.status(500).json({
+            success: false,
+            message: 'Internal server error'
+        });

Also applies to: 103-105

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/controllers/authController.ts` around lines 64 - 67, The catch
blocks in authController.ts are exposing raw error messages to clients, which
leaks internal implementation details and violates security practices. In both
the catch block around lines 64-67 and the one around lines 103-105, replace the
dynamic error.message with a fixed generic message like "Internal server error"
in the res.status(500).json() response. Keep the detailed error information
(error.message and full error object) only in server-side logging using a logger
or console.error so debugging information is available internally but not
exposed to clients.

} else {
res.status(400).json({ message: 'Invalid user data' });
}
};

// @desc Authenticate a user
// @route POST /api/users/login
// @access Public
export const loginUser = async (req: Request, res: Response) => {
const { email, password } = req.body;
try {
const { email, password } = req.body;

const user = await prisma.user.findUnique({ where: { email } });
const user = await prisma.user.findUnique({ where: { email } });

if (user && user.password && (await bcrypt.compare(password, user.password))) {
if (user.isBanned) {
res.status(403).json({ message: 'Your account has been suspended' });
return;
if (user && user.password && (await bcrypt.compare(password, user.password))) {
if (user.isBanned) {
res.status(403).json({ message: 'Your account has been suspended' });
return;
}
res.json({
_id: user.id,
name: user.name,
email: user.email,
role: user.role,
token: generateToken(user.id),
xp_points: user.xp_points,
streak_days: user.streak_days,
solvedProblems: user.solvedProblems,
bookmarks: user.bookmarks,
activityLog: user.activityLog
});
} else {
res.status(400).json({ message: 'Invalid credentials' });
}
res.json({
_id: user.id,
name: user.name,
email: user.email,
role: user.role,
token: generateToken(user.id),
xp_points: user.xp_points,
streak_days: user.streak_days,
solvedProblems: user.solvedProblems,
bookmarks: user.bookmarks,
activityLog: user.activityLog
} catch (error: any) {
console.error('Login Error:', error);

res.status(500).json({
success: false,
message: error.message || 'Internal server error'
});
} else {
res.status(400).json({ message: 'Invalid credentials' });
}
};

Expand Down Expand Up @@ -147,14 +166,18 @@ export const googleAuth = async (req: Request, res: Response) => {
});

} catch (error) {
console.error(error);
res.status(400).json({ message: 'Google Auth Failed' });
}
console.error('Google Auth Error:', error);

res.status(500).json({
success: false,
message: 'Google authentication failed'
});
}
};

// @desc Get user data
// @route GET /api/users/me
// @access Private
export const getMe = async (req: Request, res: Response) => {
res.status(200).json(req.user);
};
};