previously tokens were only like IDs, time based and incrementing counter. An attacker could easily bruteforce them. This patch changes tokens to be completely random. fixes #2
50 lines
1.6 KiB
TypeScript
50 lines
1.6 KiB
TypeScript
import crypto from "crypto";
|
|
import { defineEventHandler, getCookie, setCookie, readBody } from "h3";
|
|
|
|
import { database } from "../utils/database";
|
|
import { isString } from "../utils/isString";
|
|
import { cookieSettings } from "../utils/rootUtils";
|
|
import SessionToken from "../utils/SessionToken";
|
|
|
|
import { createError } from "#imports";
|
|
|
|
export function getPasswordHash(password: string) {
|
|
return crypto.createHmac("sha512", "42")
|
|
.update(password)
|
|
.digest();
|
|
}
|
|
|
|
export default defineEventHandler(async (e) => {
|
|
if (getCookie(e, "token"))
|
|
throw createError({ statusCode: 501, message: "Case not implemented: logging in while cookie is set" });
|
|
await new Promise(resolve => setTimeout(resolve, 420));
|
|
const data = await readBody(e);
|
|
|
|
const login = data.login;
|
|
const password = data.password;
|
|
|
|
if (!isString(login)) throw createError({ statusCode: 400, message: "Login is not string." });
|
|
if (!isString(password)) throw createError({ statusCode: 400, message: "Password is not string." });
|
|
|
|
const hashedPassword = getPasswordHash(password);
|
|
|
|
const account = await database.user.findUnique({
|
|
where: {
|
|
username: login,
|
|
password: hashedPassword,
|
|
},
|
|
select: {
|
|
id: true,
|
|
},
|
|
});
|
|
|
|
if (account === null) throw createError({ statusCode: 400, message: "Invalid username or password." });
|
|
|
|
const session = new SessionToken(account.id);
|
|
|
|
await database.session.create({
|
|
data: session.toPrisma(),
|
|
});
|
|
setCookie(e, "token", session.toString(), cookieSettings);
|
|
return { message: "Login successful", token: session.toString() };
|
|
});
|