From 8b6bbe003da39e20f282b4a275ea015dbf4ab70a Mon Sep 17 00:00:00 2001 From: KernelDeimos Date: Thu, 9 May 2024 18:04:53 -0400 Subject: [PATCH] fix(security) Disable 2FA configure if 2FA is enabled --- packages/backend/src/api/APIError.js | 4 ++++ .../backend/src/routers/auth/configure-2fa.js | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/packages/backend/src/api/APIError.js b/packages/backend/src/api/APIError.js index b3fce16d..b7591d97 100644 --- a/packages/backend/src/api/APIError.js +++ b/packages/backend/src/api/APIError.js @@ -335,6 +335,10 @@ module.exports = class APIError { status: 400, message: ({ action }) => `Invalid action: ${quot(action)}.`, }, + '2fa_already_enabled': { + status: 409, + message: '2FA is already enabled.', + }, // Object Mapping 'field_not_allowed_for_create': { diff --git a/packages/backend/src/routers/auth/configure-2fa.js b/packages/backend/src/routers/auth/configure-2fa.js index fb66ce1a..bb50379c 100644 --- a/packages/backend/src/routers/auth/configure-2fa.js +++ b/packages/backend/src/routers/auth/configure-2fa.js @@ -1,5 +1,6 @@ const APIError = require("../../api/APIError"); const eggspress = require("../../api/eggspress"); +const { get_user } = require("../../helpers"); const { UserActorType } = require("../../services/auth/Actor"); const { DB_WRITE } = require("../../services/database/consts"); const { Context } = require("../../util/context"); @@ -25,6 +26,12 @@ module.exports = eggspress('/auth/configure-2fa/:action', { const db = await x.get('services').get('database').get(DB_WRITE, '2fa'); actions.setup = async () => { + const user = await get_user({ id: req.user.id, force: true }); + + if ( user.otp_enabled ) { + throw APIError.create('2fa_already_enabled'); + } + const svc_otp = x.get('services').get('otp'); // generate secret @@ -56,6 +63,8 @@ module.exports = eggspress('/auth/configure-2fa/:action', { ); req.user.otp_secret = result.secret; req.user.otp_recovery_codes = hashed_recovery_codes.join(','); + user.otp_secret = result.secret; + user.otp_recovery_codes = hashed_recovery_codes.join(','); return result; }; @@ -77,6 +86,12 @@ module.exports = eggspress('/auth/configure-2fa/:action', { return res.status(429).send('Too many requests.'); } + const user = await get_user({ id: req.user.id, force: true }); + + if ( user.otp_enabled ) { + throw APIError.create('2fa_already_enabled'); + } + await db.write( `UPDATE user SET otp_enabled = 1 WHERE uuid = ?`, [user.uuid]