More preparations for 2 factor authentication
This commit is contained in:
parent
7389c25312
commit
0633311ba1
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,3 +7,4 @@ logs/
|
||||
*.sqlite
|
||||
yarn-error\.log
|
||||
config.ini
|
||||
.env
|
@ -1,3 +1,7 @@
|
||||
[database]
|
||||
host=localhost
|
||||
database=openauth
|
||||
|
||||
[core]
|
||||
name = OpenAuthService
|
||||
|
||||
|
103
package-lock.json
generated
103
package-lock.json
generated
@ -164,20 +164,12 @@
|
||||
}
|
||||
},
|
||||
"@types/dotenv": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "http://registry.npmjs.org/@types/dotenv/-/dotenv-4.0.3.tgz",
|
||||
"integrity": "sha512-mmhpINC/HcLGQK5ikFJlLXINVvcxhlrV+ZOUJSN7/ottYl+8X4oSXzS9lBtDkmWAl96EGyGyLrNvk9zqdSH8Fw==",
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/dotenv/-/dotenv-6.1.0.tgz",
|
||||
"integrity": "sha512-gmbNb7V1LbJQA4MmH0hVFgqY1cyKsa6RvKC1Xrq0WBnZ0JuuvXKciXx/s8dN0LVXCJd8xO6wIaSFSyUIoGph9g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "10.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.1.4.tgz",
|
||||
"integrity": "sha512-GpQxofkdlHYxjHad98UUdNoMO7JrmzQZoAaghtNg14Gwg7YkohcrCoJEcEMSgllx4VIZ+mYw7ZHjfaeIagP/rg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/events": {
|
||||
@ -252,9 +244,9 @@
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "10.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.2.tgz",
|
||||
"integrity": "sha512-53ElVDSnZeFUUFIYzI8WLQ25IhWzb6vbddNp8UHlXQyU0ET2RhV5zg0NfubzU7iNMh5bBXb0htCzfvrSVNgzaQ==",
|
||||
"version": "10.12.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.5.tgz",
|
||||
"integrity": "sha512-GzdHjq3t3eGLMv92Al90Iq+EoLL+86mPfQhuglbBFO7HiLdC/rkt+zrzJJumAiBF6nsrBWhou22rPW663AAyFw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node-rsa": {
|
||||
@ -452,15 +444,6 @@
|
||||
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
|
||||
"dev": true
|
||||
},
|
||||
"babel-runtime": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
||||
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
|
||||
"requires": {
|
||||
"core-js": "^2.4.0",
|
||||
"regenerator-runtime": "^0.11.0"
|
||||
}
|
||||
},
|
||||
"backo2": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
|
||||
@ -539,26 +522,12 @@
|
||||
"callsite": "1.0.0"
|
||||
}
|
||||
},
|
||||
"big-number": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/big-number/-/big-number-0.3.1.tgz",
|
||||
"integrity": "sha1-rHMCDApZu3nrF8LOLbd/d9l04BM="
|
||||
},
|
||||
"binary-extensions": {
|
||||
"version": "1.12.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz",
|
||||
"integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==",
|
||||
"dev": true
|
||||
},
|
||||
"bl": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
|
||||
"integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
|
||||
"requires": {
|
||||
"readable-stream": "^2.3.5",
|
||||
"safe-buffer": "^5.1.1"
|
||||
}
|
||||
},
|
||||
"blob": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
|
||||
@ -946,15 +915,11 @@
|
||||
"integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
|
||||
"dev": true
|
||||
},
|
||||
"core-js": {
|
||||
"version": "2.5.7",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
|
||||
"integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw=="
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
|
||||
"dev": true
|
||||
},
|
||||
"cors": {
|
||||
"version": "2.8.5",
|
||||
@ -2540,7 +2505,8 @@
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
|
||||
"dev": true
|
||||
},
|
||||
"isexe": {
|
||||
"version": "2.0.0",
|
||||
@ -2971,11 +2937,6 @@
|
||||
"to-regex": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"native-duplexpair": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/native-duplexpair/-/native-duplexpair-1.0.0.tgz",
|
||||
"integrity": "sha1-eJkHjmS/PIo9cyYBs9QP8F21j6A="
|
||||
},
|
||||
"negotiator": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
|
||||
@ -3337,7 +3298,8 @@
|
||||
"process-nextick-args": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
|
||||
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
|
||||
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
|
||||
"dev": true
|
||||
},
|
||||
"proxy-addr": {
|
||||
"version": "2.0.4",
|
||||
@ -3372,11 +3334,6 @@
|
||||
"ps-tree": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||
@ -3425,6 +3382,7 @@
|
||||
"version": "2.3.6",
|
||||
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
@ -3451,11 +3409,6 @@
|
||||
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.12.tgz",
|
||||
"integrity": "sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A=="
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
|
||||
},
|
||||
"regex-not": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
|
||||
@ -4026,6 +3979,7 @@
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
@ -4069,32 +4023,6 @@
|
||||
"csextends": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"tedious": {
|
||||
"version": "2.6.4",
|
||||
"resolved": "https://registry.npmjs.org/tedious/-/tedious-2.6.4.tgz",
|
||||
"integrity": "sha512-upFZB4QahZydPIV2VK3H/bz8Fsq5FSjqbxDbhhp1c/66ZJB1qCk5p1cXi2p/VUOgAYbmAzVObTg5kaVvmeyN+Q==",
|
||||
"requires": {
|
||||
"babel-runtime": "^6.26.0",
|
||||
"big-number": "0.3.1",
|
||||
"bl": "^1.2.2",
|
||||
"depd": "^1.1.2",
|
||||
"iconv-lite": "^0.4.23",
|
||||
"native-duplexpair": "^1.0.0",
|
||||
"punycode": "^2.1.0",
|
||||
"readable-stream": "^2.3.6",
|
||||
"sprintf-js": "^1.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"term-size": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz",
|
||||
@ -4399,7 +4327,8 @@
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
||||
"dev": true
|
||||
},
|
||||
"utils-merge": {
|
||||
"version": "1.0.1",
|
||||
|
@ -16,14 +16,14 @@
|
||||
"@types/body-parser": "^1.17.0",
|
||||
"@types/compression": "^0.0.36",
|
||||
"@types/cookie-parser": "^1.4.1",
|
||||
"@types/dotenv": "^4.0.3",
|
||||
"@types/dotenv": "^6.1.0",
|
||||
"@types/express": "^4.16.0",
|
||||
"@types/handlebars": "^4.0.39",
|
||||
"@types/i18n": "^0.8.3",
|
||||
"@types/ini": "^1.3.29",
|
||||
"@types/jsonwebtoken": "^8.3.0",
|
||||
"@types/mongodb": "^3.1.14",
|
||||
"@types/node": "^10.12.2",
|
||||
"@types/node": "^10.12.5",
|
||||
"@types/node-rsa": "^0.4.3",
|
||||
"@types/uuid": "^3.4.4",
|
||||
"concurrently": "^4.0.1",
|
||||
@ -48,7 +48,6 @@
|
||||
"mongodb": "^3.1.9",
|
||||
"node-rsa": "^1.0.1",
|
||||
"reflect-metadata": "^0.1.12",
|
||||
"tedious": "^2.6.4",
|
||||
"uuid": "^3.3.2"
|
||||
}
|
||||
}
|
||||
|
@ -21,11 +21,11 @@ export function GetUserMiddleware(json = false, special_token: boolean = false,
|
||||
}
|
||||
try {
|
||||
let { login, special } = req.cookies
|
||||
|
||||
if (!login) invalid()
|
||||
|
||||
let token = await LoginToken.findOne({ token: login, valid: true })
|
||||
if (!token) invalid()
|
||||
if (!token.validated) invalid();
|
||||
|
||||
let user = await User.findById(token.user);
|
||||
if (!user) {
|
||||
@ -43,7 +43,7 @@ export function GetUserMiddleware(json = false, special_token: boolean = false,
|
||||
if (special) {
|
||||
Logging.debug("Special found")
|
||||
let st = await LoginToken.findOne({ token: special, special: true, valid: true })
|
||||
if (st && st.valid && st.user.toHexString() === token.user.toHexString()) {
|
||||
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;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Request, Response } from "express"
|
||||
import User, { IUser } from "../../models/user";
|
||||
import User, { IUser, TokenTypes } from "../../models/user";
|
||||
import { randomBytes } from "crypto";
|
||||
import moment = require("moment");
|
||||
import LoginToken from "../../models/login_token";
|
||||
@ -19,14 +19,16 @@ const Login = promiseMiddleware(async (req: Request, res: Response) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const sendToken = async (user: IUser) => {
|
||||
const sendToken = async (user: IUser, tfa?: TokenTypes[]) => {
|
||||
let token_str = randomBytes(16).toString("hex");
|
||||
let tfa_exp = moment().add(5, "minutes").toDate()
|
||||
let token_exp = moment().add(6, "months").toDate()
|
||||
let token = LoginToken.new({
|
||||
token: token_str,
|
||||
valid: true,
|
||||
validTill: token_exp,
|
||||
user: user._id
|
||||
validTill: tfa ? tfa_exp : token_exp,
|
||||
user: user._id,
|
||||
validated: tfa ? false : true
|
||||
});
|
||||
await LoginToken.save(token);
|
||||
|
||||
@ -35,15 +37,17 @@ const Login = promiseMiddleware(async (req: Request, res: Response) => {
|
||||
let special = LoginToken.new({
|
||||
token: special_str,
|
||||
valid: true,
|
||||
validTill: special_exp,
|
||||
validTill: tfa ? tfa_exp : special_exp,
|
||||
special: true,
|
||||
user: user._id
|
||||
user: user._id,
|
||||
validated: tfa ? false : true
|
||||
});
|
||||
await LoginToken.save(special);
|
||||
|
||||
res.json({
|
||||
login: { token: token_str, expires: token_exp.toUTCString() },
|
||||
special: { token: special_str, expires: special_exp.toUTCString() }
|
||||
login: { token: token_str, expires: token.validTill.toUTCString() },
|
||||
special: { token: special_str, expires: special.validTill.toUTCString() },
|
||||
tfa
|
||||
});
|
||||
}
|
||||
|
||||
@ -61,12 +65,8 @@ const Login = promiseMiddleware(async (req: Request, res: Response) => {
|
||||
|
||||
} else {
|
||||
if (user.twofactor && user.twofactor.length > 0) {
|
||||
let types = user.twofactor.map(f => {
|
||||
return { type: f.type };
|
||||
})
|
||||
res.json({
|
||||
types: types
|
||||
});
|
||||
let types = user.twofactor.filter(f => f.valid).map(f => f.type)
|
||||
await sendToken(user, types);
|
||||
} else {
|
||||
await sendToken(user);
|
||||
}
|
||||
|
@ -1,11 +1,6 @@
|
||||
export interface DatabaseConfig {
|
||||
host: string
|
||||
database: string
|
||||
dialect: "sqlite" | "mysql" | "postgres" | "mssql"
|
||||
username: string
|
||||
password: string
|
||||
storage: string
|
||||
benchmark: "true" | "false" | undefined
|
||||
}
|
||||
|
||||
export interface WebConfig {
|
||||
@ -37,7 +32,7 @@ import { Logging } from "@hibas123/nodelogging";
|
||||
dotenv.config();
|
||||
|
||||
const config: Config = ini.parse(readFileSync("./config.ini").toString())
|
||||
|
||||
if (config.dev) config.dev = Boolean(config.dev);
|
||||
if (process.env.DEV === "true") {
|
||||
config.dev = true;
|
||||
Logging.warning("DEV mode active. This can cause major performance issues, data loss and vulnerabilities! ")
|
||||
|
@ -1,3 +1,11 @@
|
||||
import SafeMongo from "@hibas123/safe_mongo";
|
||||
const DB = new SafeMongo("mongodb://localhost", "openauth");
|
||||
import Config from "./config"
|
||||
let dbname = "openauth"
|
||||
let host = "localhost"
|
||||
if (Config.database) {
|
||||
if (Config.database.database) dbname = Config.database.database;
|
||||
if (Config.database.host) host = Config.database.host;
|
||||
}
|
||||
if (Config.dev) dbname += "_dev";
|
||||
const DB = new SafeMongo("mongodb://" + host, dbname);
|
||||
export default DB;
|
@ -8,6 +8,7 @@ export interface ILoginToken extends ModelDataBase {
|
||||
user: ObjectID;
|
||||
validTill: Date;
|
||||
valid: boolean;
|
||||
validated: boolean;
|
||||
}
|
||||
const LoginToken = DB.addModel<ILoginToken>({
|
||||
name: "login_token",
|
||||
@ -20,6 +21,16 @@ const LoginToken = DB.addModel<ILoginToken>({
|
||||
validTill: { type: Date },
|
||||
valid: { type: Boolean }
|
||||
}
|
||||
}, {
|
||||
migration: (doc: ILoginToken) => { doc.validated = true; },
|
||||
schema: {
|
||||
token: { type: String },
|
||||
special: { type: Boolean, default: () => false },
|
||||
user: { type: ObjectID },
|
||||
validTill: { type: Date },
|
||||
valid: { type: Boolean },
|
||||
validated: { type: Boolean, default: false }
|
||||
}
|
||||
}]
|
||||
})
|
||||
|
||||
|
@ -9,7 +9,6 @@ import * as cookieparser from "cookie-parser"
|
||||
|
||||
import * as i18n from "i18n"
|
||||
import * as compression from "compression";
|
||||
import { BADHINTS } from "dns";
|
||||
import ApiRouter from "./api/api";
|
||||
import ViewRouter from "./views/views";
|
||||
import RequestError, { HttpStatusCode } from "./helper/request_error";
|
||||
|
@ -75,10 +75,7 @@ loginbutton.onclick = async () => {
|
||||
loading();
|
||||
let pw = sha(salt + passwordinput.value);
|
||||
try {
|
||||
let {
|
||||
login,
|
||||
special
|
||||
} = await fetch("/api/user/login?type=password", {
|
||||
let { login, special, tfa } = await fetch("/api/user/login?type=password", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
username: usernameinput.value,
|
||||
|
Loading…
Reference in New Issue
Block a user