import { Router } from "express" import Stacker from "../../../middlewares/stacker"; import { GetUserMiddleware } from "../../../middlewares/user"; import TwoFactor, { TFATypes as TwoFATypes, IBackupCode } from "../../../../models/twofactor"; import RequestError, { HttpStatusCode } from "../../../../helper/request_error"; import moment = require("moment"); import { upgradeToken } from "../helper"; import * as crypto from "crypto"; import Logging from "@hibas123/nodelogging"; const BackupCodeRoute = Router(); // TODO: Further checks if this is good enough randomness function generateCode(length: number) { let bytes = crypto.randomBytes(length); let nrs = ""; bytes.forEach((b, idx) => { let nr = Math.floor((b / 255) * 9.9999) if (nr > 9) nr = 9; nrs += String(nr); }) return nrs; } BackupCodeRoute.post("/", Stacker(GetUserMiddleware(true, true), async (req, res) => { //Generating new let codes = Array(10).map(() => generateCode(8)); console.log(codes); let twofactor = TwoFactor.new({ user: req.user._id, type: TwoFATypes.OTC, valid: true, data: codes, name: "" }) await TwoFactor.save(twofactor); res.json({ codes, id: twofactor._id }) })); BackupCodeRoute.put("/", Stacker(GetUserMiddleware(true, false, undefined, false), async (req, res) => { let { login, special } = req.token; let { id, code }: { id: string, code: string } = req.body; let twofactor: IBackupCode = await TwoFactor.findById(id); if (!twofactor || !twofactor.valid || !twofactor.user.equals(req.user._id) || twofactor.type !== TwoFATypes.OTC) { throw new RequestError("Invalid Method!", HttpStatusCode.BAD_REQUEST); } if (twofactor.expires && moment().isAfter(twofactor.expires)) { twofactor.valid = false; await TwoFactor.save(twofactor); throw new RequestError("Invalid Method!", HttpStatusCode.BAD_REQUEST); } code = code.replace(/\s/g, ""); let valid = twofactor.data.find(c => c === code); if (valid) { twofactor.data = twofactor.data.filter(c => c !== code); await TwoFactor.save(twofactor); let [login_exp, special_exp] = await Promise.all([ upgradeToken(login), upgradeToken(special) ]); res.json({ success: true, login_exp, special_exp }) } else { throw new RequestError("Invalid or already used code!", HttpStatusCode.BAD_REQUEST); } })) export default BackupCodeRoute;