From 35938db24b1474f6358877cc537f7492322d7271 Mon Sep 17 00:00:00 2001 From: Julian Gassner Date: Wed, 15 Jan 2025 14:33:11 +0000 Subject: [PATCH] Added MFA to model and internal user --- backend/internal/user.js | 32 ++++++++++++++ .../20250115041439_mfa_integeration.js | 43 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 backend/migrations/20250115041439_mfa_integeration.js diff --git a/backend/internal/user.js b/backend/internal/user.js index 742ab65d..e3b6d155 100644 --- a/backend/internal/user.js +++ b/backend/internal/user.js @@ -7,6 +7,8 @@ const authModel = require('../models/auth'); const gravatar = require('gravatar'); const internalToken = require('./token'); const internalAuditLog = require('./audit-log'); +const authenticator = require('authenticator'); +const qrcode = require('qrcode'); function omissions () { return ['is_deleted']; @@ -507,6 +509,36 @@ const internalUser = { .then((user) => { return internalToken.getTokenFromUser(user); }); + }, + + createMFAKey: (access, data) => { + return access.can('users:activate_mfa', data.id) + .then(() => { + return internalUser.get(access, {id: data.id}); + }) + .then((user) => { + let secret = authenticator.generateKey(); + return userModel + .query() + .patchAndFetchById(user.id, { mfa_key: secret }) + .then(() => { + let uri = authenticator.generateTotpUri(secret, user.email, 'NginxProxyManager'); + return qrcode.toDataURL(uri); + }) + .then((qrCode) => { + return { user, qrCode }; + }); + }) + .then(({ user, qrCode }) => { + return internalAuditLog.add(access, { + action: 'updated', + object_type: 'user', + object_id: user.id, + meta: data + + }) + .then(() => ({ user, qrCode })); + }); } }; diff --git a/backend/migrations/20250115041439_mfa_integeration.js b/backend/migrations/20250115041439_mfa_integeration.js new file mode 100644 index 00000000..0f9d009e --- /dev/null +++ b/backend/migrations/20250115041439_mfa_integeration.js @@ -0,0 +1,43 @@ +const migrate_name = 'identifier_for_migrate'; +const logger = require('../logger').migrate; + +/** + * Migrate + * + * @see http://knexjs.org/#Schema + * + * @param {Object} knex + * @param {Promise} Promise + * @returns {Promise} + */ +exports.up = function (knex/*, Promise*/) { + + logger.info('[' + migrate_name + '] Migrating Up...'); + + return knex.schema.alterTable('user', (table) => { + table.string('mfa_secret'); + }) + .then(() => { + logger.info('[' + migrate_name + '] User Table altered'); + logger.info('[' + migrate_name + '] Migrating Up Complete'); + }); +}; + +/** + * Undo Migrate + * + * @param {Object} knex + * @param {Promise} Promise + * @returns {Promise} + */ +exports.down = function (knex/*, Promise*/) { + logger.info('[' + migrate_name + '] Migrating Down...'); + + return knex.schema.alterTable('user', (table) => { + table.dropColumn('mfa_key'); + }) + .then(() => { + logger.info('[' + migrate_name + '] User Table altered'); + logger.info('[' + migrate_name + '] Migrating Down Complete'); + }); +};