Merge pull request from GHSA-g9v2-wqcj-j99g

* Fix attempt

* Update message
This commit is contained in:
Louis Lam 2023-10-09 07:01:54 +08:00 committed by GitHub
parent bd9c44cccf
commit 88afab6571
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 9 deletions

View File

@ -1,6 +1,8 @@
const { BeanModel } = require("redbean-node/dist/bean-model"); const { BeanModel } = require("redbean-node/dist/bean-model");
const passwordHash = require("../password-hash"); const passwordHash = require("../password-hash");
const { R } = require("redbean-node"); const { R } = require("redbean-node");
const jwt = require("jsonwebtoken");
const { shake256, SHAKE256_LENGTH } = require("../util-server");
class User extends BeanModel { class User extends BeanModel {
/** /**
@ -27,6 +29,19 @@ class User extends BeanModel {
this.password = newPassword; this.password = newPassword;
} }
/**
* Create a new JWT for a user
* @param {User} user
* @param {string} jwtSecret
* @return {string}
*/
static createJWT(user, jwtSecret) {
return jwt.sign({
username: user.username,
h: shake256(user.password, SHAKE256_LENGTH),
}, jwtSecret);
}
} }
module.exports = User; module.exports = User;

View File

@ -83,8 +83,11 @@ const app = server.app;
log.info("server", "Importing this project modules"); log.info("server", "Importing this project modules");
log.debug("server", "Importing Monitor"); log.debug("server", "Importing Monitor");
const Monitor = require("./model/monitor"); const Monitor = require("./model/monitor");
const User = require("./model/user");
log.debug("server", "Importing Settings"); log.debug("server", "Importing Settings");
const { getSettings, setSettings, setting, initJWTSecret, checkLogin, startUnitTest, FBSD, doubleCheckPassword, startE2eTests } = require("./util-server"); const { getSettings, setSettings, setting, initJWTSecret, checkLogin, startUnitTest, FBSD, doubleCheckPassword, startE2eTests, shake256, SHAKE256_LENGTH
} = require("./util-server");
log.debug("server", "Importing Notification"); log.debug("server", "Importing Notification");
const { Notification } = require("./notification"); const { Notification } = require("./notification");
@ -296,6 +299,11 @@ let needSetup = false;
decoded.username, decoded.username,
]); ]);
// Check if the password changed
if (decoded.h !== shake256(user.password, SHAKE256_LENGTH)) {
throw new Error("The token is invalid due to password change or old token");
}
if (user) { if (user) {
log.debug("auth", "afterLogin"); log.debug("auth", "afterLogin");
afterLogin(socket, user); afterLogin(socket, user);
@ -316,9 +324,10 @@ let needSetup = false;
}); });
} }
} catch (error) { } catch (error) {
log.error("auth", `Invalid token. IP=${clientIP}`); log.error("auth", `Invalid token. IP=${clientIP}`);
if (error.message) {
log.error("auth", error.message, `IP=${clientIP}`);
}
callback({ callback({
ok: false, ok: false,
msg: "Invalid token.", msg: "Invalid token.",
@ -357,9 +366,7 @@ let needSetup = false;
callback({ callback({
ok: true, ok: true,
token: jwt.sign({ token: User.createJWT(user, server.jwtSecret),
username: data.username,
}, server.jwtSecret),
}); });
} }
@ -387,9 +394,7 @@ let needSetup = false;
callback({ callback({
ok: true, ok: true,
token: jwt.sign({ token: User.createJWT(user, server.jwtSecret),
username: data.username,
}, server.jwtSecret),
}); });
} else { } else {

View File

@ -33,6 +33,7 @@ const dayjs = require("dayjs");
// SASLOptions used in JSDoc // SASLOptions used in JSDoc
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
const { Kafka, SASLOptions } = require("kafkajs"); const { Kafka, SASLOptions } = require("kafkajs");
const crypto = require("crypto");
const isWindows = process.platform === /^win/.test(process.platform); const isWindows = process.platform === /^win/.test(process.platform);
/** /**
@ -1055,6 +1056,23 @@ module.exports.grpcQuery = async (options) => {
}); });
}; };
module.exports.SHAKE256_LENGTH = 16;
/**
*
* @param {string} data
* @param {number} len
* @return {string}
*/
module.exports.shake256 = (data, len) => {
if (!data) {
return "";
}
return crypto.createHash("shake256", { outputLength: len })
.update(data)
.digest("hex");
};
// For unit test, export functions // For unit test, export functions
if (process.env.TEST_BACKEND) { if (process.env.TEST_BACKEND) {
module.exports.__test = { module.exports.__test = {