diff --git a/packages/backend-core/encryption.js b/packages/backend-core/encryption.js new file mode 100644 index 0000000000..4ccb6e3a99 --- /dev/null +++ b/packages/backend-core/encryption.js @@ -0,0 +1 @@ +module.exports = require("./src/security/encryption") diff --git a/packages/backend-core/src/middleware/authenticated.js b/packages/backend-core/src/middleware/authenticated.js index 2d24f7fb21..0cb56b5b69 100644 --- a/packages/backend-core/src/middleware/authenticated.js +++ b/packages/backend-core/src/middleware/authenticated.js @@ -6,6 +6,7 @@ const { buildMatcherRegex, matches } = require("./matchers") const env = require("../environment") const { SEPARATOR, ViewNames, queryGlobalView } = require("../../db") const { getGlobalDB } = require("../tenancy") +const { decrypt } = require("../security/encryption") function finalise( ctx, @@ -22,6 +23,7 @@ async function checkApiKey(apiKey, populateUser) { if (apiKey === env.INTERNAL_API_KEY) { return { valid: true } } + apiKey = decrypt(apiKey) const tenantId = apiKey.split(SEPARATOR)[0] const db = getGlobalDB(tenantId) const userId = await queryGlobalView( diff --git a/packages/backend-core/src/security/encryption.js b/packages/backend-core/src/security/encryption.js new file mode 100644 index 0000000000..8bb7def541 --- /dev/null +++ b/packages/backend-core/src/security/encryption.js @@ -0,0 +1,27 @@ +const crypto = require("crypto") +const env = require("../environment") + +const ALGO = "aes-256-ctr" +const SECRET = env.JWT_SECRET +const SEPARATOR = "/" + +exports.encrypt = input => { + const random = crypto.randomBytes(16) + const cipher = crypto.createCipheriv(ALGO, SECRET, random) + const base = cipher.update(input) + const final = cipher.final() + const encrypted = Buffer.concat([base, final]).toString("hex") + return `${random.toString("hex")}${SEPARATOR}${encrypted}` +} + +exports.decrypt = input => { + const [random, encrypted] = input.split(SEPARATOR) + const decipher = crypto.createDecipheriv( + ALGO, + SECRET, + Buffer.from(random, "hex") + ) + const base = decipher.update(Buffer.from(encrypted, "hex")) + const final = decipher.final() + return Buffer.concat([base, final]).toString() +} diff --git a/packages/worker/src/api/controllers/global/self.js b/packages/worker/src/api/controllers/global/self.js index 26e07e63bb..ea29c496e8 100644 --- a/packages/worker/src/api/controllers/global/self.js +++ b/packages/worker/src/api/controllers/global/self.js @@ -2,11 +2,12 @@ const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy") const { generateDevInfoID, SEPARATOR } = require("@budibase/backend-core/db") const { user: userCache } = require("@budibase/backend-core/cache") const { hash, platformLogout } = require("@budibase/backend-core/utils") +const { encrypt } = require("@budibase/backend-core/encryption") const { newid } = require("@budibase/backend-core/utils") const { getUser } = require("../../utilities") function newApiKey() { - return hash(`${getTenantId()}${SEPARATOR}${newid()}`) + return encrypt(`${getTenantId()}${SEPARATOR}${newid()}`) } function cleanupDevInfo(info) { @@ -25,7 +26,7 @@ exports.generateAPIKey = async ctx => { } catch (err) { devInfo = { _id: id, userId: ctx.user._id } } - devInfo.apiKey = newApiKey() + devInfo.apiKey = await newApiKey() await db.put(devInfo) ctx.body = cleanupDevInfo(devInfo) } @@ -40,7 +41,7 @@ exports.fetchAPIKey = async ctx => { devInfo = { _id: id, userId: ctx.user._id, - apiKey: newApiKey(), + apiKey: await newApiKey(), } await db.put(devInfo) }