import { Request, Response } from "express"; import { verifyPassword } from "../lib/crypto"; import { User } from "../models/user/user.model"; import { sign, decode, verify } from 'jsonwebtoken'; import { JWT_SECRET, logger } from "../app"; import { LivebeatRequest } from '../lib/request'; import { SchemaTypes } from "mongoose"; export async function GetUser(req: Request, res: Response) { } export async function DeleteUser(req: Request, res: Response) { } export async function PatchUser(req: Request, res: Response) { } export async function LoginUser(req: Request, res: Response) { const username = req.body.username; const password = req.body.password; const twoFA = req.body.twoFA; const user = await User.findOne({ name: username }); // Check if user exists if (user == undefined) { setTimeout(() => { res.status(404).send({ message: "Either the username or password is wrong." }); }, Math.random() * 1500 + 400); return; } // Check if 2FA is turned on (the attack doesn't know yet if the password is wrong) if (user.twoFASecret != undefined) { if (twoFA == undefined) { res.status(401).send({ message: "2FA code is required." }); return; } // TODO: Implement 2FA logic here } // Check if password is wrong if (!await verifyPassword(password + user.salt, user.password)) { res.status(404).send({ message: 'Either the username or password is wrong.' }); return; } // We're good. Create JWT token. const token = sign({ user: user._id }, JWT_SECRET, { expiresIn: '30d' }); logger.info(`User ${user.name} logged in.`) res.status(200).send({ token }); } /** * This middleware validates any tokens that are required to access most of the endpoints. * Note: This validation doesn't contain any permission checking. */ export async function MW_User(req: LivebeatRequest, res: Response, next: () => void) { if (req.headers.token === undefined) { res.status(401).send({ message: "Token not specified" }); return; } const token = req.headers.token.toString(); try { // Verify token if(await verify(token, JWT_SECRET, { algorithms: ['HS256'] })) { // Token is valid, now look if user is in db (in case he got deleted) const id = decode(token, { json: true })!.user; const db = await User.findById(id); if (db !== undefined && db !== null) { req.user = db next(); return; } else { res.status(401).send({ message: "Token is not valid" }); } } else { res.status(401).send({ message: "Token is not valid" }); } } catch (err) { if (err) { res.status(500).send({ message: "We failed validating your token for some reason." }); logger.error(err); } } }