From a5c7eb3a27e09227a24022a9ab387959fc7c9781 Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Fri, 28 Jul 2023 14:22:10 +0200 Subject: [PATCH] Move user token signing to UserManager Only the controller has access to the secret needed to sign user tokens so it makes sense for the user signing code to live in the controller. This saves about 20ms on the time ctl takes to start up due to lib no longer needing to import jsonwebtoken. --- packages/controller/controller.js | 5 +++-- packages/controller/src/UserManager.js | 15 +++++++++++++++ packages/lib/package.json | 1 - packages/lib/src/users.js | 12 ------------ packages/web_ui/webpack.common.js | 4 ---- plugins/player_auth/controller.js | 2 +- test/mock.js | 2 +- 7 files changed, 20 insertions(+), 21 deletions(-) diff --git a/packages/controller/controller.js b/packages/controller/controller.js index ca505621..c42892a3 100755 --- a/packages/controller/controller.js +++ b/packages/controller/controller.js @@ -130,7 +130,7 @@ async function handleBootstrapCommand(args, controllerConfig) { return; } // eslint-disable-next-line no-console - console.log(user.createToken(controllerConfig.get("controller.auth_secret"))); + console.log(userManager.signUserToken(user.name)); } else if (subCommand === "generate-host-token") { // eslint-disable-next-line no-console @@ -151,7 +151,8 @@ async function handleBootstrapCommand(args, controllerConfig) { controlConfig.set("control.controller_url", Controller.calculateControllerUrl(controllerConfig)); controlConfig.set( - "control.controller_token", admin.createToken(controllerConfig.get("controller.auth_secret")) + "control.controller_token", + userManager.signUserToken(admin.name), ); let content = JSON.stringify(controlConfig.serialize(), null, 4); diff --git a/packages/controller/src/UserManager.js b/packages/controller/src/UserManager.js index b40ca3bd..312b291c 100644 --- a/packages/controller/src/UserManager.js +++ b/packages/controller/src/UserManager.js @@ -1,5 +1,6 @@ "use strict"; const fs = require("fs-extra"); +const jwt = require("jsonwebtoken"); const lib = require("@clusterio/lib"); @@ -83,6 +84,20 @@ class UserManager { this.users.set(name, user); return user; } + + /** + * Sign access token for the given user name + * + * @param {string} name - user name to sign token for + * @returns {string} JWT access token for the user. + */ + signUserToken(name) { + return jwt.sign( + { aud: "user", user: name }, + Buffer.from(this._config.get("controller.auth_secret"), "base64") + ); + } + } module.exports = UserManager; diff --git a/packages/lib/package.json b/packages/lib/package.json index 994ef166..635d1599 100644 --- a/packages/lib/package.json +++ b/packages/lib/package.json @@ -16,7 +16,6 @@ "chalk": "^4.1.2", "fast-deep-equal": "^3.1.3", "fs-extra": "^11.1.1", - "jsonwebtoken": "^9.0.1", "jszip": "^3.10.1", "klaw": "^4.1.0", "set-blocking": "^2.0.0", diff --git a/packages/lib/src/users.js b/packages/lib/src/users.js index b13ec9b2..5e505fc4 100644 --- a/packages/lib/src/users.js +++ b/packages/lib/src/users.js @@ -7,8 +7,6 @@ * @module lib/users */ "use strict"; -const jwt = require("jsonwebtoken"); - const libErrors = require("./errors"); const PlayerStats = require("./PlayerStats"); @@ -257,16 +255,6 @@ class User { return serialized; } - /** - * Generate access token for this user - * - * @param {string} secret - Secret to sign token with. - * @returns {string} JWT access token for the user. - */ - createToken(secret) { - return jwt.sign({ aud: "user", user: this.name }, Buffer.from(secret, "base64")); - } - /** * Invalidate current tokens for the user * diff --git a/packages/web_ui/webpack.common.js b/packages/web_ui/webpack.common.js index ebaab0ea..6a2b3dcc 100644 --- a/packages/web_ui/webpack.common.js +++ b/packages/web_ui/webpack.common.js @@ -44,10 +44,6 @@ module.exports = (env = {}) => ({ test: /node_modules.fs-extra/, use: require.resolve("null-loader"), }, - { - test: /node_modules.jsonwebtoken/, - use: require.resolve("null-loader"), - }, { test: /node_modules.winston.dist.winston.transports.(http|file)/, use: require.resolve("null-loader"), diff --git a/plugins/player_auth/controller.js b/plugins/player_auth/controller.js index 95d63fc2..03f27374 100644 --- a/plugins/player_auth/controller.js +++ b/plugins/player_auth/controller.js @@ -149,7 +149,7 @@ class ControllerPlugin extends lib.BaseControllerPlugin { return; } - let token = user.createToken(secret); + let token = this.controller.userManager.signUserToken(user.name); res.send({ verified: true, token }); return; diff --git a/test/mock.js b/test/mock.js index eb73ae66..21be1360 100644 --- a/test/mock.js +++ b/test/mock.js @@ -165,7 +165,7 @@ class MockController { }, }; - this.userManager = new UserManager(); + this.userManager = new UserManager(this.config); this.userManager.roles = new Map([ [0, new lib.Role({ id: 0, name: "Admin", description: "admin", permissions: ["core.admin"] })], [1, new lib.Role({ id: 1, name: "Player", description: "player", permissions: [] })],