Skip to content

Commit

Permalink
bug: Security vulnerabilities in external Login API endpoint (code100…
Browse files Browse the repository at this point in the history
…x#1417)

fix: Fix timing attacks in externalLogin route
  • Loading branch information
kushwahramkumar2003 authored Oct 20, 2024
1 parent 5802927 commit 4b71e99
Showing 1 changed file with 40 additions and 15 deletions.
55 changes: 40 additions & 15 deletions src/app/api/admin/services/externalLogin/route.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { z } from 'zod';
import db from '@/db';
import { NextRequest, NextResponse } from 'next/server';
import bcrypt from 'bcrypt';

const loginSchema = z.object({
email: z.string(),
password: z.string(),
});

export async function POST(req: NextRequest) {
const authKey = req.headers.get('Auth-Key');

Expand All @@ -11,46 +17,65 @@ export async function POST(req: NextRequest) {

try {
const payload = await req.json();
const { email, password } = payload;

const result = loginSchema.safeParse(payload);
if (!result.success) {
return NextResponse.json(
{ message: 'Invalid input', errors: result.error.errors },
{ status: 400 },
);
}

const { email, password } = result.data;

const user = await db.user.findFirst({
where: {
email,
},
where: { email },
select: {
id: true,
email: true,
name: true,
password: true,
},
});
if (!user) {
return NextResponse.json({ message: 'User not found' }, { status: 404 });

// Perform a dummy bcrypt compare if user doesn't exist to prevent timing attacks
if (!user || !user.password) {
await bcrypt.compare(password, await bcrypt.hash('dummy', 10));
return NextResponse.json(
{ message: 'Invalid credentials' },
{ status: 401 },
);
}

if (
user &&
user.password &&
(await bcrypt.compare(password, user.password))
) {
const isPasswordValid = await bcrypt.compare(password, user.password);

if (isPasswordValid) {
const courses = await db.course.findMany({
where: {
purchasedBy: {
some: {
user: {
email,
},
user: { email },
},
},
},
});

return NextResponse.json({
message: 'User found',
data: {
user,
user: {
id: user.id,
email: user.email,
name: user.name,
},
courses,
},
});
}
return NextResponse.json(
{ message: 'Invalid credentials' },
{ status: 401 },
);
} catch (error) {
return NextResponse.json(
{ message: 'Error fetching user' },
Expand Down

0 comments on commit 4b71e99

Please sign in to comment.