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;