🕸️ refactor: Migrate from crypto to Web Crypto API (#3357)

* move crypto to async webcrypto

update encrypt/decrypt

forgot await

* chore: import order - openidStrategy.js

* chore: import order - Session.js

* chore: import order - AuthController.js

* Update AuthService.js

---------

Co-authored-by: Danny Avila <danacordially@gmail.com>
This commit is contained in:
matt burnett 2024-08-04 23:59:45 -04:00 committed by GitHub
parent b6fe7e5570
commit 3e0f95458f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 108 additions and 51 deletions

View file

@ -116,8 +116,8 @@ async function loadActionSets(searchParams) {
* @param {ActionRequest} params.requestBuilder - The ActionRequest builder class to execute the API call.
* @returns { { _call: (toolInput: Object) => unknown} } An object with `_call` method to execute the tool input.
*/
function createActionTool({ action, requestBuilder }) {
action.metadata = decryptMetadata(action.metadata);
async function createActionTool({ action, requestBuilder }) {
action.metadata = await decryptMetadata(action.metadata);
const _call = async (toolInput) => {
try {
requestBuilder.setParams(toolInput);
@ -153,23 +153,23 @@ function createActionTool({ action, requestBuilder }) {
* @param {ActionMetadata} metadata - The action metadata to encrypt.
* @returns {ActionMetadata} The updated action metadata with encrypted values.
*/
function encryptMetadata(metadata) {
async function encryptMetadata(metadata) {
const encryptedMetadata = { ...metadata };
// ServiceHttp
if (metadata.auth && metadata.auth.type === AuthTypeEnum.ServiceHttp) {
if (metadata.api_key) {
encryptedMetadata.api_key = encryptV2(metadata.api_key);
encryptedMetadata.api_key = await encryptV2(metadata.api_key);
}
}
// OAuth
else if (metadata.auth && metadata.auth.type === AuthTypeEnum.OAuth) {
if (metadata.oauth_client_id) {
encryptedMetadata.oauth_client_id = encryptV2(metadata.oauth_client_id);
encryptedMetadata.oauth_client_id = await encryptV2(metadata.oauth_client_id);
}
if (metadata.oauth_client_secret) {
encryptedMetadata.oauth_client_secret = encryptV2(metadata.oauth_client_secret);
encryptedMetadata.oauth_client_secret = await encryptV2(metadata.oauth_client_secret);
}
}
@ -182,23 +182,23 @@ function encryptMetadata(metadata) {
* @param {ActionMetadata} metadata - The action metadata to decrypt.
* @returns {ActionMetadata} The updated action metadata with decrypted values.
*/
function decryptMetadata(metadata) {
async function decryptMetadata(metadata) {
const decryptedMetadata = { ...metadata };
// ServiceHttp
if (metadata.auth && metadata.auth.type === AuthTypeEnum.ServiceHttp) {
if (metadata.api_key) {
decryptedMetadata.api_key = decryptV2(metadata.api_key);
decryptedMetadata.api_key = await decryptV2(metadata.api_key);
}
}
// OAuth
else if (metadata.auth && metadata.auth.type === AuthTypeEnum.OAuth) {
if (metadata.oauth_client_id) {
decryptedMetadata.oauth_client_id = decryptV2(metadata.oauth_client_id);
decryptedMetadata.oauth_client_id = await decryptV2(metadata.oauth_client_id);
}
if (metadata.oauth_client_secret) {
decryptedMetadata.oauth_client_secret = decryptV2(metadata.oauth_client_secret);
decryptedMetadata.oauth_client_secret = await decryptV2(metadata.oauth_client_secret);
}
}

View file

@ -1,4 +1,3 @@
const crypto = require('crypto');
const bcrypt = require('bcryptjs');
const { SystemRoles, errorsToString } = require('librechat-data-provider');
const {
@ -12,6 +11,7 @@ const {
} = require('~/models/userMethods');
const { sendEmail, checkEmailConfig } = require('~/server/utils');
const { registerSchema } = require('~/strategies/validators');
const { hashToken } = require('~/server/utils/crypto');
const isDomainAllowed = require('./isDomainAllowed');
const Token = require('~/models/schema/tokenSchema');
const Session = require('~/models/Session');
@ -34,7 +34,7 @@ const genericVerificationMessage = 'Please check your email to verify your email
*/
const logoutUser = async (userId, refreshToken) => {
try {
const hash = crypto.createHash('sha256').update(refreshToken).digest('hex');
const hash = await hashToken(refreshToken);
// Find the session with the matching user and refreshTokenHash
const session = await Session.findOne({ user: userId, refreshTokenHash: hash });

View file

@ -29,7 +29,7 @@ const getUserPluginAuthValue = async (userId, authField) => {
throw new Error(`No plugin auth ${authField} found for user ${userId}`);
}
const decryptedValue = decrypt(pluginAuth.value);
const decryptedValue = await decrypt(pluginAuth.value);
return decryptedValue;
} catch (err) {
logger.error('[getUserPluginAuthValue]', err);
@ -64,7 +64,7 @@ const getUserPluginAuthValue = async (userId, authField) => {
const updateUserPluginAuth = async (userId, authField, pluginKey, value) => {
try {
const encryptedValue = encrypt(value);
const encryptedValue = await encrypt(value);
const pluginAuth = await PluginAuth.findOne({ userId, authField }).lean();
if (pluginAuth) {
const pluginAuth = await PluginAuth.updateOne(

View file

@ -335,7 +335,7 @@ async function processRequiredActions(client, requiredActions) {
continue;
}
tool = createActionTool({ action: actionSet, requestBuilder });
tool = await createActionTool({ action: actionSet, requestBuilder });
isActionTool = !!tool;
ActionToolMap[currentAction.tool] = tool;
}

View file

@ -50,7 +50,7 @@ const getUserKey = async ({ userId, name }) => {
}),
);
}
return decrypt(keyValue.value);
return await decrypt(keyValue.value);
};
/**
@ -109,7 +109,7 @@ const getUserKeyExpiry = async ({ userId, name }) => {
* after encrypting the provided value. It sets the provided expiry date for the key.
*/
const updateUserKey = async ({ userId, name, value, expiresAt = null }) => {
const encryptedValue = encrypt(value);
const encryptedValue = await encrypt(value);
let updateObject = {
userId,
name,