Added U2F Support for YubiKey
This commit is contained in:
@ -1,8 +1,8 @@
|
||||
import { Request, Router } from "express";
|
||||
import ClientRoute from "./admin/client";
|
||||
import UserRoute from "./admin/user";
|
||||
import RegCodeRoute from "./admin/regcode";
|
||||
import PermissionRoute from "./admin/permission";
|
||||
import ClientRoute from "./client";
|
||||
import UserRoute from "./user";
|
||||
import RegCodeRoute from "./regcode";
|
||||
import PermissionRoute from "./permission";
|
||||
|
||||
const AdminRoute: Router = Router();
|
||||
AdminRoute.use("/client", ClientRoute);
|
@ -14,6 +14,9 @@ ApiRouter.use("/user", UserRoute);
|
||||
ApiRouter.use("/internal", InternalRoute);
|
||||
ApiRouter.use("/oauth", OAuthRoute);
|
||||
|
||||
ApiRouter.use("/client/user", AuthGetUser);
|
||||
|
||||
// Legacy reasons (deprecated)
|
||||
ApiRouter.use("/user", AuthGetUser);
|
||||
|
||||
// Legacy reasons (deprecated)
|
@ -1,6 +1,6 @@
|
||||
import { Router } from "express";
|
||||
import { OAuthInternalApp } from "./internal/oauth";
|
||||
import PasswordAuth from "./internal/password";
|
||||
import { OAuthInternalApp } from "./oauth";
|
||||
import PasswordAuth from "./password";
|
||||
|
||||
const InternalRoute: Router = Router();
|
||||
InternalRoute.get("/oauth", OAuthInternalApp);
|
@ -1,7 +1,9 @@
|
||||
import { Request, Response, NextFunction, RequestHandler } from "express";
|
||||
import promiseMiddleware from "../../helper/promiseMiddleware";
|
||||
|
||||
function call(handler: RequestHandler, req: Request, res: Response) {
|
||||
type RH = (req: Request, res: Response, next?: NextFunction) => any;
|
||||
|
||||
function call(handler: RH, req: Request, res: Response) {
|
||||
return new Promise((yes, no) => {
|
||||
let p = handler(req, res, (err) => {
|
||||
if (err) no(err);
|
||||
@ -11,7 +13,7 @@ function call(handler: RequestHandler, req: Request, res: Response) {
|
||||
})
|
||||
}
|
||||
|
||||
const Stacker = (...handler: RequestHandler[]) => {
|
||||
const Stacker = (...handler: RH[]) => {
|
||||
return promiseMiddleware(async (req: Request, res: Response, next: NextFunction) => {
|
||||
let hc = handler.concat();
|
||||
while (hc.length > 0) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import LoginToken from "../../models/login_token";
|
||||
import LoginToken, { CheckToken } from "../../models/login_token";
|
||||
import Logging from "@hibas123/nodelogging";
|
||||
import RequestError, { HttpStatusCode } from "../../helper/request_error";
|
||||
import User from "../../models/user";
|
||||
@ -14,7 +14,7 @@ class Invalid extends Error { }
|
||||
* @param json Checks if requests wants an json or html for returning errors
|
||||
* @param redirect_uri Sets the uri to redirect, if json is not set and user not logged in
|
||||
*/
|
||||
export function GetUserMiddleware(json = false, special_token: boolean = false, redirect_uri?: string) {
|
||||
export function GetUserMiddleware(json = false, special_required: boolean = false, redirect_uri?: string, validated = true) {
|
||||
return promiseMiddleware(async function (req: Request, res: Response, next?: NextFunction) {
|
||||
const invalid = () => {
|
||||
throw new Invalid();
|
||||
@ -24,8 +24,7 @@ export function GetUserMiddleware(json = false, special_token: boolean = false,
|
||||
if (!login) invalid()
|
||||
|
||||
let token = await LoginToken.findOne({ token: login, valid: true })
|
||||
if (!token) invalid()
|
||||
if (!token.validated) invalid();
|
||||
if (!await CheckToken(token, validated)) invalid();
|
||||
|
||||
let user = await User.findById(token.user);
|
||||
if (!user) {
|
||||
@ -34,31 +33,23 @@ export function GetUserMiddleware(json = false, special_token: boolean = false,
|
||||
invalid();
|
||||
}
|
||||
|
||||
if (token.validTill.getTime() < new Date().getTime()) { //Token expired
|
||||
token.valid = false;
|
||||
await LoginToken.save(token);
|
||||
invalid()
|
||||
}
|
||||
|
||||
let special_token;
|
||||
if (special) {
|
||||
Logging.debug("Special found")
|
||||
let st = await LoginToken.findOne({ token: special, special: true, valid: true })
|
||||
if (st && st.validated && st.valid && st.user.toHexString() === token.user.toHexString()) {
|
||||
if (st.validTill.getTime() < new Date().getTime()) { //Token expired
|
||||
Logging.debug("Special expired")
|
||||
st.valid = false;
|
||||
await LoginToken.save(st);
|
||||
} else {
|
||||
Logging.debug("Special valid")
|
||||
req.special = true;
|
||||
}
|
||||
}
|
||||
special_token = await LoginToken.findOne({ token: special, special: true, valid: true, user: token.user })
|
||||
if (!await CheckToken(special_token, validated))
|
||||
invalid();
|
||||
req.special = true;
|
||||
}
|
||||
|
||||
if (special_token && !req.special) invalid();
|
||||
if (special_required && !req.special) invalid();
|
||||
|
||||
req.user = user
|
||||
req.isAdmin = user.admin;
|
||||
req.token = {
|
||||
login: token,
|
||||
special: special_token
|
||||
}
|
||||
|
||||
if (next)
|
||||
next()
|
||||
@ -67,7 +58,7 @@ export function GetUserMiddleware(json = false, special_token: boolean = false,
|
||||
if (e instanceof Invalid) {
|
||||
if (req.method === "GET" && !json) {
|
||||
res.status(HttpStatusCode.UNAUTHORIZED)
|
||||
res.redirect("/login?base64=true&state=" + new Buffer(redirect_uri ? redirect_uri : req.originalUrl).toString("base64"))
|
||||
res.redirect("/login?base64=true&state=" + Buffer.from(redirect_uri ? redirect_uri : req.originalUrl).toString("base64"))
|
||||
} else {
|
||||
throw new RequestError(req.__("You are not logged in or your login is expired"), HttpStatusCode.UNAUTHORIZED)
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Router } from "express";
|
||||
import AuthRoute from "./oauth/auth";
|
||||
import JWTRoute from "./oauth/jwt";
|
||||
import Public from "./oauth/public";
|
||||
import RefreshTokenRoute from "./oauth/refresh";
|
||||
import AuthRoute from "./auth";
|
||||
import JWTRoute from "./jwt";
|
||||
import Public from "./public";
|
||||
import RefreshTokenRoute from "./refresh";
|
||||
|
||||
const OAuthRoue: Router = Router();
|
||||
OAuthRoue.post("/auth", AuthRoute);
|
@ -1,8 +0,0 @@
|
||||
import { Request, Router } from "express";
|
||||
import Register from "./user/register";
|
||||
import Login from "./user/login";
|
||||
|
||||
const UserRoute: Router = Router();
|
||||
UserRoute.post("/register", Register);
|
||||
UserRoute.post("/login", Login)
|
||||
export default UserRoute;
|
14
src/api/user/index.ts
Normal file
14
src/api/user/index.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { Router } from "express";
|
||||
import Register from "./register";
|
||||
import Login from "./login";
|
||||
import TwoFactorRoute from "./twofactor";
|
||||
import { GetToken, DeleteToken } from "./token";
|
||||
|
||||
const UserRoute: Router = Router();
|
||||
UserRoute.post("/register", Register);
|
||||
UserRoute.post("/login", Login)
|
||||
UserRoute.use("/twofactor", TwoFactorRoute);
|
||||
|
||||
UserRoute.get("/token", GetToken);
|
||||
UserRoute.delete("/token", DeleteToken);
|
||||
export default UserRoute;
|
@ -1,10 +1,12 @@
|
||||
import { Request, Response } from "express"
|
||||
import User, { IUser, TokenTypes } from "../../models/user";
|
||||
import User, { IUser } from "../../models/user";
|
||||
import { randomBytes } from "crypto";
|
||||
import moment = require("moment");
|
||||
import LoginToken from "../../models/login_token";
|
||||
import RequestError, { HttpStatusCode } from "../../helper/request_error";
|
||||
import promiseMiddleware from "../../helper/promiseMiddleware";
|
||||
import * as speakeasy from "speakeasy";
|
||||
import TwoFactor from "../../models/twofactor";
|
||||
|
||||
const Login = promiseMiddleware(async (req: Request, res: Response) => {
|
||||
let type = req.query.type;
|
||||
@ -19,7 +21,13 @@ const Login = promiseMiddleware(async (req: Request, res: Response) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const sendToken = async (user: IUser, tfa?: TokenTypes[]) => {
|
||||
const sendToken = async (user: IUser, tfa?: any[]) => {
|
||||
let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress
|
||||
let client = {
|
||||
ip: Array.isArray(ip) ? ip[0] : ip,
|
||||
browser: req.headers["user-agent"]
|
||||
}
|
||||
|
||||
let token_str = randomBytes(16).toString("hex");
|
||||
let tfa_exp = moment().add(5, "minutes").toDate()
|
||||
let token_exp = moment().add(6, "months").toDate()
|
||||
@ -28,7 +36,8 @@ const Login = promiseMiddleware(async (req: Request, res: Response) => {
|
||||
valid: true,
|
||||
validTill: tfa ? tfa_exp : token_exp,
|
||||
user: user._id,
|
||||
validated: tfa ? false : true
|
||||
validated: tfa ? false : true,
|
||||
...client
|
||||
});
|
||||
await LoginToken.save(token);
|
||||
|
||||
@ -40,7 +49,8 @@ const Login = promiseMiddleware(async (req: Request, res: Response) => {
|
||||
validTill: tfa ? tfa_exp : special_exp,
|
||||
special: true,
|
||||
user: user._id,
|
||||
validated: tfa ? false : true
|
||||
validated: tfa ? false : true,
|
||||
...client
|
||||
});
|
||||
await LoginToken.save(special);
|
||||
|
||||
@ -51,7 +61,7 @@ const Login = promiseMiddleware(async (req: Request, res: Response) => {
|
||||
});
|
||||
}
|
||||
|
||||
if (type === "password" || type === "twofactor") {
|
||||
if (type === "password") {
|
||||
let { username, password, uid } = req.body;
|
||||
|
||||
let user = await User.findOne(username ? { username: username.toLowerCase() } : { uid: uid })
|
||||
@ -61,20 +71,29 @@ const Login = promiseMiddleware(async (req: Request, res: Response) => {
|
||||
if (user.password !== password) {
|
||||
res.json({ error: req.__("Password or username wrong") })
|
||||
} else {
|
||||
if (type === "twofactor") {
|
||||
|
||||
let twofactor = await TwoFactor.find({ user: user._id, valid: true })
|
||||
let expired = twofactor.filter(e => e.expires ? moment().isAfter(moment(e.expires)) : false)
|
||||
await Promise.all(expired.map(e => {
|
||||
e.valid = false;
|
||||
return TwoFactor.save(e);
|
||||
}));
|
||||
twofactor = twofactor.filter(e => e.valid);
|
||||
if (twofactor && twofactor.length > 0) {
|
||||
let tfa = twofactor.map(e => {
|
||||
return {
|
||||
id: e._id,
|
||||
name: e.name,
|
||||
type: e.type
|
||||
}
|
||||
})
|
||||
await sendToken(user, tfa);
|
||||
} else {
|
||||
if (user.twofactor && user.twofactor.length > 0) {
|
||||
let types = user.twofactor.filter(f => f.valid).map(f => f.type)
|
||||
await sendToken(user, types);
|
||||
} else {
|
||||
await sendToken(user);
|
||||
}
|
||||
await sendToken(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new RequestError("Invalid type!", HttpStatusCode.BAD_REQUEST);
|
||||
res.json({ error: req.__("Invalid type!") });
|
||||
}
|
||||
});
|
||||
|
||||
|
29
src/api/user/token.ts
Normal file
29
src/api/user/token.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { Request, Response } from "express";
|
||||
import Stacker from "../middlewares/stacker";
|
||||
import { GetUserMiddleware } from "../middlewares/user";
|
||||
import LoginToken, { CheckToken } from "../../models/login_token";
|
||||
import RequestError, { HttpStatusCode } from "../../helper/request_error";
|
||||
|
||||
export const GetToken = Stacker(GetUserMiddleware(true, true), async (req: Request, res: Response) => {
|
||||
let raw_token = await LoginToken.find({ user: req.user._id, valid: true });
|
||||
let token = await Promise.all(raw_token.map(async token => {
|
||||
await CheckToken(token);
|
||||
return {
|
||||
id: token._id,
|
||||
special: token.special,
|
||||
ip: token.ip,
|
||||
browser: token.browser,
|
||||
isthis: token._id.equals(token.special ? req.token.special._id : req.token.login._id)
|
||||
}
|
||||
}).filter(t => t !== undefined));
|
||||
res.json({ token });
|
||||
});
|
||||
|
||||
export const DeleteToken = Stacker(GetUserMiddleware(true, true), async (req: Request, res: Response) => {
|
||||
let { id } = req.query;
|
||||
let token = await LoginToken.findById(id);
|
||||
if (!token || !token.user.equals(req.user._id)) throw new RequestError("Invalid ID", HttpStatusCode.BAD_REQUEST);
|
||||
token.valid = false;
|
||||
await LoginToken.save(token);
|
||||
res.json({ success: true });
|
||||
});
|
79
src/api/user/twofactor/helper.ts
Normal file
79
src/api/user/twofactor/helper.ts
Normal file
@ -0,0 +1,79 @@
|
||||
import LoginToken, { ILoginToken } from "../../../models/login_token";
|
||||
import moment = require("moment");
|
||||
|
||||
// export async function unlockToken() {
|
||||
// let { type, code, login, special } = req.body;
|
||||
|
||||
// let [login_t, special_t] = await Promise.all([LoginToken.findOne({ token: login }), LoginToken.findOne({ token: special })]);
|
||||
|
||||
// if ((login && !login_t) || (special && !special_t)) {
|
||||
// res.json({ error: req.__("Token not found!") });
|
||||
// } else {
|
||||
// let atoken = special_t || login_t;
|
||||
|
||||
// let user = await User.findById(atoken.user);
|
||||
|
||||
// let tf = await TwoFactor.find({ user: user._id, valid: true })
|
||||
|
||||
// let valid = false;
|
||||
// switch (type) {
|
||||
// case TokenTypes.OTC: {
|
||||
// let twofactor = await TwoFactor.findOne({ type, valid: true })
|
||||
// if (twofactor) {
|
||||
// valid = speakeasy.totp.verify({
|
||||
// secret: twofactor.token,
|
||||
// encoding: "base64",
|
||||
// token: code
|
||||
// })
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
|
||||
// case TokenTypes.BACKUP_CODE: {
|
||||
// let twofactor = await TwoFactor.findOne({ type, valid: true, token: code })
|
||||
// if (twofactor) {
|
||||
// twofactor.valid = false;
|
||||
// await TwoFactor.save(twofactor);
|
||||
// valid = true;
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// case TokenTypes.APP_ALLOW:
|
||||
// case TokenTypes.YUBI_KEY:
|
||||
// default:
|
||||
// res.json({ error: req.__("Invalid twofactor!") });
|
||||
// return;
|
||||
|
||||
// }
|
||||
|
||||
// if (!valid) {
|
||||
// res.json({ error: req.__("Invalid code!") });
|
||||
// return;
|
||||
// }
|
||||
|
||||
// let result: any = {};
|
||||
// if (login_t) {
|
||||
// login_t.validated = true
|
||||
// await LoginToken.save(login_t)
|
||||
// result.login = { token: login_t.token, expires: login_t.validTill.toUTCString() }
|
||||
// }
|
||||
|
||||
// if (special_t) {
|
||||
// special_t.validated = true;
|
||||
// await LoginToken.save(special_t);
|
||||
// result.special = { token: special_t.token, expires: special_t.validTill.toUTCString() }
|
||||
// }
|
||||
// res.json(result);
|
||||
// }
|
||||
// }
|
||||
|
||||
export async function upgradeToken(token: ILoginToken) {
|
||||
token.data = undefined;
|
||||
token.valid = true;
|
||||
token.validated = true;
|
||||
//TODO durations from config
|
||||
let expires = (token.special ? moment().add(30, "minute") : moment().add(6, "months")).toDate();
|
||||
token.validTill = expires;
|
||||
await LoginToken.save(token);
|
||||
return expires;
|
||||
}
|
43
src/api/user/twofactor/index.ts
Normal file
43
src/api/user/twofactor/index.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import { Router } from "express";
|
||||
import YubiKeyRoute from "./yubikey";
|
||||
import { GetUserMiddleware } from "../../middlewares/user";
|
||||
import Stacker from "../../middlewares/stacker";
|
||||
import TwoFactor from "../../../models/twofactor";
|
||||
import * as moment from "moment"
|
||||
import RequestError, { HttpStatusCode } from "../../../helper/request_error";
|
||||
|
||||
|
||||
const TwoFactorRouter = Router();
|
||||
|
||||
TwoFactorRouter.get("/", Stacker(GetUserMiddleware(true, true), async (req, res) => {
|
||||
let twofactor = await TwoFactor.find({ user: req.user._id, valid: true })
|
||||
let expired = twofactor.filter(e => e.expires ? moment().isAfter(moment(e.expires)) : false)
|
||||
await Promise.all(expired.map(e => {
|
||||
e.valid = false;
|
||||
return TwoFactor.save(e);
|
||||
}));
|
||||
twofactor = twofactor.filter(e => e.valid);
|
||||
let tfa = twofactor.map(e => {
|
||||
return {
|
||||
id: e._id,
|
||||
name: e.name,
|
||||
type: e.type
|
||||
}
|
||||
})
|
||||
res.json({ methods: tfa });
|
||||
}));
|
||||
|
||||
TwoFactorRouter.delete("/", Stacker(GetUserMiddleware(true, true), async (req, res) => {
|
||||
let { id } = req.query;
|
||||
let tfa = await TwoFactor.findById(id);
|
||||
if (!tfa || !tfa.user.equals(req.user._id)) {
|
||||
throw new RequestError("Invalid id", HttpStatusCode.BAD_REQUEST);
|
||||
}
|
||||
tfa.valid = false;
|
||||
await TwoFactor.save(tfa);
|
||||
res.json({ success: true });
|
||||
}));
|
||||
|
||||
TwoFactorRouter.use("/yubikey", YubiKeyRoute);
|
||||
|
||||
export default TwoFactorRouter;
|
131
src/api/user/twofactor/yubikey/index.ts
Normal file
131
src/api/user/twofactor/yubikey/index.ts
Normal file
@ -0,0 +1,131 @@
|
||||
import { Router, Request } from "express"
|
||||
import Stacker from "../../../middlewares/stacker";
|
||||
import { UserMiddleware, GetUserMiddleware } from "../../../middlewares/user";
|
||||
import * as u2f from "u2f";
|
||||
import config from "../../../../config";
|
||||
import TwoFactor, { TFATypes as TwoFATypes, IYubiKey } from "../../../../models/twofactor";
|
||||
import RequestError, { HttpStatusCode } from "../../../../helper/request_error";
|
||||
import moment = require("moment");
|
||||
import LoginToken from "../../../../models/login_token";
|
||||
import { upgradeToken } from "../helper";
|
||||
import Logging from "@hibas123/nodelogging";
|
||||
|
||||
const U2FRoute = Router();
|
||||
|
||||
U2FRoute.post("/", Stacker(GetUserMiddleware(true, true), async (req, res) => {
|
||||
const { type } = req.query;
|
||||
if (type === "challenge") {
|
||||
const registrationRequest = u2f.request(config.core.url);
|
||||
|
||||
let twofactor = TwoFactor.new(<IYubiKey>{
|
||||
user: req.user._id,
|
||||
type: TwoFATypes.U2F,
|
||||
valid: false,
|
||||
data: {
|
||||
registration: registrationRequest
|
||||
}
|
||||
})
|
||||
await TwoFactor.save(twofactor);
|
||||
res.json({ request: registrationRequest, id: twofactor._id, appid: config.core.url });
|
||||
} else {
|
||||
const { response, id } = req.body;
|
||||
Logging.debug(req.body, id);
|
||||
let twofactor: IYubiKey = await TwoFactor.findById(id);
|
||||
const err = () => { throw new RequestError("Invalid ID!", HttpStatusCode.BAD_REQUEST) };
|
||||
if (!twofactor || !twofactor.user.equals(req.user._id) || twofactor.type !== TwoFATypes.U2F || !twofactor.data.registration || twofactor.valid) {
|
||||
Logging.debug("Not found or wrong user", twofactor);
|
||||
err();
|
||||
}
|
||||
|
||||
if (twofactor.expires && moment().isAfter(moment(twofactor.expires))) {
|
||||
await TwoFactor.delete(twofactor);
|
||||
Logging.debug("Expired!", twofactor);
|
||||
err();
|
||||
}
|
||||
|
||||
const result = u2f.checkRegistration(twofactor.data.registration, response);
|
||||
|
||||
if (result.successful) {
|
||||
twofactor.data = {
|
||||
keyHandle: result.keyHandle,
|
||||
publicKey: result.publicKey
|
||||
}
|
||||
twofactor.expires = undefined;
|
||||
twofactor.valid = true;
|
||||
await TwoFactor.save(twofactor);
|
||||
res.json({ success: true });
|
||||
} else {
|
||||
throw new RequestError(result.errorMessage, HttpStatusCode.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
U2FRoute.get("/", Stacker(GetUserMiddleware(true, false, undefined, false), async (req, res) => {
|
||||
let { login, special } = req.token;
|
||||
let twofactor: IYubiKey = await TwoFactor.findOne({ user: req.user._id, type: TwoFATypes.U2F, valid: true })
|
||||
|
||||
if (!twofactor) {
|
||||
throw new RequestError("Invalid Method!", HttpStatusCode.BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (twofactor.expires) {
|
||||
if (moment().isAfter(twofactor.expires)) {
|
||||
twofactor.valid = false;
|
||||
await TwoFactor.save(twofactor);
|
||||
throw new RequestError("Invalid Method!", HttpStatusCode.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
let request = u2f.request(config.core.url, twofactor.data.keyHandle);
|
||||
login.data = {
|
||||
type: "ykr",
|
||||
request
|
||||
};
|
||||
let r;;
|
||||
if (special) {
|
||||
special.data = login.data;
|
||||
r = LoginToken.save(special);
|
||||
}
|
||||
|
||||
await Promise.all([r, LoginToken.save(login)]);
|
||||
res.json({ request });
|
||||
}))
|
||||
|
||||
U2FRoute.put("/", Stacker(GetUserMiddleware(true, false, undefined, false), async (req, res) => {
|
||||
let { login, special } = req.token;
|
||||
let twofactor: IYubiKey = await TwoFactor.findOne({ user: req.user._id, type: TwoFATypes.U2F, valid: true })
|
||||
|
||||
|
||||
let { response } = req.body;
|
||||
if (!twofactor || !login.data || login.data.type !== "ykr" || special && (!special.data || special.data.type !== "ykr")) {
|
||||
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);
|
||||
}
|
||||
|
||||
let login_exp;
|
||||
let special_exp;
|
||||
let result = u2f.checkSignature(login.data.request, response, twofactor.data.publicKey);
|
||||
if (result.successful) {
|
||||
if (special) {
|
||||
let result = u2f.checkSignature(special.data.request, response, twofactor.data.publicKey);
|
||||
if (result.successful) {
|
||||
special_exp = await upgradeToken(special);
|
||||
}
|
||||
else {
|
||||
throw new RequestError(result.errorMessage, HttpStatusCode.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
login_exp = await upgradeToken(login);
|
||||
}
|
||||
else {
|
||||
throw new RequestError(result.errorMessage, HttpStatusCode.BAD_REQUEST);
|
||||
}
|
||||
res.json({ success: true, login_exp, special_exp })
|
||||
}))
|
||||
|
||||
export default U2FRoute;
|
Reference in New Issue
Block a user