From f8633b839e7501e890264c9129a867a3e96859ce Mon Sep 17 00:00:00 2001 From: Tben <52448020+BenjaminToby@users.noreply.github.com> Date: Sat, 6 May 2023 12:14:09 +0100 Subject: [PATCH] updates --- functions/decrypt.js | 21 +++++++ functions/encrypt.js | 21 +++++++ index.js | 8 +++ users/add-user.js | 88 ++++++++++++++++++++++++++ users/login-user.js | 143 +++++++++++++++++++++++++++++++++++++++++++ users/logout-user.js | 40 ++++++++++++ users/user-auth.js | 97 +++++++++++++++++++++++++++++ 7 files changed, 418 insertions(+) create mode 100644 functions/decrypt.js create mode 100644 functions/encrypt.js create mode 100644 users/add-user.js create mode 100644 users/login-user.js create mode 100644 users/logout-user.js create mode 100644 users/user-auth.js diff --git a/functions/decrypt.js b/functions/decrypt.js new file mode 100644 index 0000000..d121455 --- /dev/null +++ b/functions/decrypt.js @@ -0,0 +1,21 @@ +const { scryptSync, createDecipheriv } = require("crypto"); +const { Buffer } = require("buffer"); + +const decrypt = ({ encryptedString, encryptionKey, encryptionSalt }) => { + const algorithm = "aes-192-cbc"; + const password = encryptionKey; + + let key = scryptSync(password, encryptionSalt, 24); + let iv = Buffer.alloc(16, 0); + const decipher = createDecipheriv(algorithm, key, iv); + + try { + let decrypted = decipher.update(encryptedString, "hex", "utf8"); + decrypted += decipher.final("utf8"); + return decrypted; + } catch (error) { + return null; + } +}; + +module.exports = decrypt; diff --git a/functions/encrypt.js b/functions/encrypt.js new file mode 100644 index 0000000..193b052 --- /dev/null +++ b/functions/encrypt.js @@ -0,0 +1,21 @@ +const { scryptSync, createCipheriv } = require("crypto"); +const { Buffer } = require("buffer"); + +const encrypt = ({ data, encryptionKey, encryptionSalt }) => { + const algorithm = "aes-192-cbc"; + const password = encryptionKey; + + let key = scryptSync(password, encryptionSalt, 24); + let iv = Buffer.alloc(16, 0); + const cipher = createCipheriv(algorithm, key, iv); + + try { + let encrypted = cipher.update(data, "utf8", "hex"); + encrypted += cipher.final("hex"); + return encrypted; + } catch (error) { + return null; + } +}; + +module.exports = encrypt; diff --git a/index.js b/index.js index 4b327b5..93cb05c 100644 --- a/index.js +++ b/index.js @@ -6,6 +6,10 @@ const get = require("./utils/get"); const post = require("./utils/post"); const uploadImage = require("./utils/upload-image"); +const createUser = require("./users/add-user"); +const loginUser = require("./users/login-user"); +const logoutUser = require("./users/logout-user"); +const userAuth = require("./users/user-auth"); /** ****************************************************************************** */ /** ****************************************************************************** */ @@ -24,6 +28,10 @@ const datasquirel = { get: get, post: post, uploadImage: uploadImage, + createUser: createUser, + loginUser: loginUser, + logoutUser: logoutUser, + userAuth: userAuth, }; module.exports = datasquirel; diff --git a/users/add-user.js b/users/add-user.js new file mode 100644 index 0000000..d2e1311 --- /dev/null +++ b/users/add-user.js @@ -0,0 +1,88 @@ +/** + * ============================================================================== + * Imports + * ============================================================================== + */ +const https = require("https"); + +/** ****************************************************************************** */ +/** ****************************************************************************** */ +/** ****************************************************************************** */ +/** ****************************************************************************** */ +/** ****************************************************************************** */ +/** ****************************************************************************** */ + +/** + * ============================================================================== + * Main Function + * ============================================================================== + * @param {String} key - API Key + * @param {String} database - Target Database + * @param {String | Object} payload - SQL query String or Request Object. Eg. { + action: "insert | update | delete", + data: { + user_id: user.id, + user_first_name: user.first_name, + user_last_name: user.last_name, + }, + table: "posts", + } + */ +module.exports = async function ({ key, payload, database }) { + /** + * Make https request + * + * @description make a request to datasquirel.com + */ + const httpResponse = await new Promise((resolve, reject) => { + https + .request( + { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: key, + }, + port: 443, + hostname: "datasquirel.com", + path: `/api/user/add-user`, + }, + + /** + * Callback Function + * + * @description https request callback + */ + (response) => { + var str = ""; + + response.on("data", function (chunk) { + str += chunk; + }); + + response.on("end", function () { + resolve(JSON.parse(str)); + }); + + response.on("error", (err) => { + reject(err); + }); + } + ) + .write({ + payload, + database, + }) + .end(); + }); + + /** ********************************************** */ + /** ********************************************** */ + /** ********************************************** */ + + return httpResponse; +}; + +/** ********************************************** */ +/** ********************************************** */ +/** ********************************************** */ diff --git a/users/login-user.js b/users/login-user.js new file mode 100644 index 0000000..c315b3b --- /dev/null +++ b/users/login-user.js @@ -0,0 +1,143 @@ +/** + * ============================================================================== + * Imports + * ============================================================================== + */ +const https = require("https"); +const encrypt = require("../functions/encrypt"); + +/** ****************************************************************************** */ +/** ****************************************************************************** */ +/** ****************************************************************************** */ +/** ****************************************************************************** */ +/** ****************************************************************************** */ +/** ****************************************************************************** */ + +/** + * ============================================================================== + * Main Function + * ============================================================================== + * @param {String} key - API Key + * @param {String} database - Target Database + * @param {Object} payload - SQL query String or Request Object. Eg. { + action: "insert | update | delete", + data: { + user_id: user.id, + user_first_name: user.first_name, + user_last_name: user.last_name, + }, + table: "posts", + } + * @param {Object} response - Http response object + * @param {String} encryptionKey - Encryption Key + * @param {String} encryptionSalt - Encryption Salt + */ +module.exports = async function ({ key, payload, database, response, encryptionKey, encryptionSalt }) { + /** + * Check Encryption Keys + * + * @description Check Encryption Keys + */ + if (!encryptionKey?.match(/./)) + return { + success: false, + payload: null, + msg: "Encryption Key Required", + }; + + if (!encryptionSalt?.match(/./)) + return { + success: false, + payload: null, + msg: "Encryption Salt Required", + }; + + if (encryptionKey.length < 24) + return { + success: false, + payload: null, + msg: "Encryption Key must be at least 24 characters", + }; + + if (encryptionSalt.length < 8) + return { + success: false, + payload: null, + msg: "Encryption Salt must be at least 8 characters", + }; + + /** + * Make https request + * + * @description make a request to datasquirel.com + */ + const httpResponse = await new Promise((resolve, reject) => { + https + .request( + { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: key, + }, + port: 443, + hostname: "datasquirel.com", + path: `/api/user/login-user`, + }, + + /** + * Callback Function + * + * @description https request callback + */ + (response) => { + var str = ""; + + response.on("data", function (chunk) { + str += chunk; + }); + + response.on("end", function () { + resolve(JSON.parse(str)); + }); + + response.on("error", (err) => { + reject(err); + }); + } + ) + .write({ + payload, + database, + }) + .end(); + }); + + /** ********************************************** */ + /** ********************************************** */ + /** ********************************************** */ + /** + * Make https request + * + * @description make a request to datasquirel.com + */ + if (httpResponse?.success) { + let encryptedPayload = encrypt({ + data: JSON.stringify(httpResponse.payload), + encryptionKey, + encryptionSalt, + }); + + response.setHeader("Set-Cookie", [`datasquirelAuthKey=${encryptedPayload};samesite=strict;path=/;HttpOnly=true;Secure=true`, `csrf=${httpResponse.csrf};samesite=strict;path=/;HttpOnly=true`]); + } + + /** ********************************************** */ + /** ********************************************** */ + /** ********************************************** */ + + return httpResponse; +}; + +/** ********************************************** */ +/** ********************************************** */ +/** ********************************************** */ diff --git a/users/logout-user.js b/users/logout-user.js new file mode 100644 index 0000000..b8a8c2b --- /dev/null +++ b/users/logout-user.js @@ -0,0 +1,40 @@ +/** + * ============================================================================== + * Imports + * ============================================================================== + */ + +/** ****************************************************************************** */ +/** ****************************************************************************** */ +/** ****************************************************************************** */ +/** ****************************************************************************** */ +/** ****************************************************************************** */ +/** ****************************************************************************** */ + +/** + * ============================================================================== + * Main Function + * ============================================================================== + * @param {Object} response - Http response object + */ +module.exports = async function ({ response }) { + /** + * Check Encryption Keys + * + * @description Check Encryption Keys + */ + response.setHeader("Set-Cookie", ["datasquirelAuthKey=none;max-age=0", "usertype=none;max-age=0", `refresh_properties=1;Max-Age=7000`]); + + /** ********************************************** */ + /** ********************************************** */ + /** ********************************************** */ + + return { + success: true, + payload: "User Logged Out", + }; +}; + +/** ********************************************** */ +/** ********************************************** */ +/** ********************************************** */ diff --git a/users/user-auth.js b/users/user-auth.js new file mode 100644 index 0000000..eed113b --- /dev/null +++ b/users/user-auth.js @@ -0,0 +1,97 @@ +/** + * ============================================================================== + * Imports + * ============================================================================== + */ +const decrypt = require("../functions/decrypt"); + +/** ****************************************************************************** */ +/** ****************************************************************************** */ +/** ****************************************************************************** */ +/** ****************************************************************************** */ +/** ****************************************************************************** */ +/** ****************************************************************************** */ + +/** + * ============================================================================== + * Main Function + * ============================================================================== + * @param {Object} request - Http request object + * @param {String} encryptionKey - Encryption Key + * @param {String} encryptionSalt - Encryption Salt + */ +module.exports = async function ({ request, encryptionKey, encryptionSalt }) { + /** + * Grab the payload + * + * @description Grab the payload + */ + let userPayload = decrypt({ + encryptedString: request.cookies.datasquirelAuthKey, + encryptionKey, + encryptionSalt, + }); + + /** + * Grab the payload + * + * @description Grab the payload + */ + if (!userPayload) { + return { + success: false, + payload: null, + msg: "Couldn't Decrypt cookie", + }; + } + + /** + * Grab the payload + * + * @description Grab the payload + */ + let userObject = JSON.parse(userPayload); + + if (!userObject.csrf_k) { + return { + success: false, + payload: null, + msg: "No CSRF_K in decrypted payload", + }; + } + + /** ********************************************** */ + /** ********************************************** */ + /** ********************************************** */ + + /** + * Grab the payload + * + * @description Grab the payload + */ + if (csrf && !req.headers["x-csrf-auth"]?.match(new RegExp(`${userObject.csrf_k}`))) { + return { + success: false, + payload: null, + msg: "CSRF_K requested but does not match payload", + }; + } + + /** ********************************************** */ + /** ********************************************** */ + /** ********************************************** */ + + /** + * Return User Object + * + * @description Return User Object + */ + return { + success: true, + payload: userObject, + }; +}; + +/** ********************************************** */ +/** ********************************************** */ +/** ********************************************** */