feat: login IT con allowlist (scrypt+HMAC) + middleware protege tablero/gestion
This commit is contained in:
1 parent
08bf7254a1
commit
57b64af1ba
13 files changed
+392
-14
No files matched your search
@@ -0,0 +1,36 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { COOKIE, isAllowed, parseUsers, signSession, verifyPassword, SESSION_MAX_AGE } from "@/lib/auth";
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
try {
|
||||
const { email, password } = await req.json();
|
||||
const mail = String(email || "").trim().toLowerCase();
|
||||
if (!mail || !password) {
|
||||
return NextResponse.json({ error: "Faltan credenciales" }, { status: 400 });
|
||||
}
|
||||
const users = parseUsers();
|
||||
const hash = users.get(mail);
|
||||
if (!hash || !isAllowed(mail) || !(await verifyPassword(String(password), hash))) {
|
||||
// Mensaje genérico: no revela si el correo existe
|
||||
await new Promise((r) => setTimeout(r, 600));
|
||||
return NextResponse.json({ error: "Credenciales inválidas" }, { status: 401 });
|
||||
}
|
||||
const res = NextResponse.json({ ok: true, email: mail });
|
||||
res.cookies.set(COOKIE, await signSession(mail), {
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
sameSite: "lax",
|
||||
path: "/",
|
||||
maxAge: SESSION_MAX_AGE,
|
||||
});
|
||||
return res;
|
||||
} catch {
|
||||
return NextResponse.json({ error: "Error interno" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE() {
|
||||
const res = NextResponse.json({ ok: true });
|
||||
res.cookies.set(COOKIE, "", { httpOnly: true, secure: true, sameSite: "lax", path: "/", maxAge: 0 });
|
||||
return res;
|
||||
}
|
||||
Reference in new issue
Block a user