Ver Fonte

RHL-005-fix(auth): add defensive check for missing passwordHash in login endpoint

Code_Uwe há 1 dia atrás
pai
commit
927e1b8005

+ 5 - 0
app/api/auth/login/route.js

@@ -49,6 +49,11 @@ export async function POST(request) {
 			return jsonResponse({ error: "Invalid credentials" }, 401);
 		}
 
+		// Defensive: never let missing/invalid passwordHash crash the endpoint.
+		if (typeof user.passwordHash !== "string" || !user.passwordHash) {
+			return jsonResponse({ error: "Invalid credentials" }, 401);
+		}
+
 		const passwordMatches = await bcrypt.compare(password, user.passwordHash);
 
 		if (!passwordMatches) {

+ 26 - 2
app/api/auth/login/route.test.js

@@ -2,7 +2,6 @@
 import { describe, it, expect, vi, beforeEach } from "vitest";
 
 // 1) Mocks
-
 vi.mock("@/lib/db", () => ({
 	getDb: vi.fn(),
 }));
@@ -26,7 +25,6 @@ vi.mock("bcryptjs", () => {
 });
 
 // 2) Imports AFTER the mocks
-
 import { getDb } from "@/lib/db";
 import User from "@/models/user";
 import { createSession } from "@/lib/auth/session";
@@ -107,6 +105,32 @@ describe("POST /api/auth/login", () => {
 		expect(createSession).not.toHaveBeenCalled();
 	});
 
+	it("returns 401 when passwordHash is missing (defensive)", async () => {
+		User.findOne.mockReturnValue({
+			exec: vi.fn().mockResolvedValue({
+				_id: "507f1f77bcf86cd799439099",
+				username: "branchuser",
+				// passwordHash missing on purpose
+				role: "branch",
+				branchId: "NL01",
+			}),
+		});
+
+		const request = createRequestStub({
+			username: "branchuser",
+			password: "secret-password",
+		});
+
+		const response = await POST(request);
+		const json = await response.json();
+
+		expect(response.status).toBe(401);
+		expect(json).toEqual({ error: "Invalid credentials" });
+
+		expect(bcryptCompare).not.toHaveBeenCalled();
+		expect(createSession).not.toHaveBeenCalled();
+	});
+
 	it("returns 401 when password is incorrect", async () => {
 		const user = {
 			_id: "507f1f77bcf86cd799439012",

+ 2 - 1
app/api/auth/logout/route.js

@@ -1,3 +1,4 @@
+// app/api/auth/logout/route.js
 import { destroySession } from "@/lib/auth/session";
 
 /**
@@ -8,7 +9,7 @@ import { destroySession } from "@/lib/auth/session";
  */
 export async function GET() {
 	try {
-		destroySession();
+		await destroySession();
 
 		return new Response(JSON.stringify({ ok: true }), {
 			status: 200,