diff --git a/backend/src/db/schemas/secret-sharing.ts b/backend/src/db/schemas/secret-sharing.ts index be5643e2b..de75fbafc 100644 --- a/backend/src/db/schemas/secret-sharing.ts +++ b/backend/src/db/schemas/secret-sharing.ts @@ -21,7 +21,6 @@ export const SecretSharingSchema = z.object({ expiresAfterViews: z.number().nullable().optional(), accessType: z.string().default("anyone"), name: z.string().nullable().optional(), - password: z.string().nullable().optional(), lastViewedAt: z.date().nullable().optional() }); diff --git a/backend/src/server/routes/v1/secret-sharing-router.ts b/backend/src/server/routes/v1/secret-sharing-router.ts index 22279d8ea..5fedfd5a0 100644 --- a/backend/src/server/routes/v1/secret-sharing-router.ts +++ b/backend/src/server/routes/v1/secret-sharing-router.ts @@ -1,4 +1,3 @@ -import bcrypt from "bcrypt"; import { z } from "zod"; import { SecretSharingSchema } from "@app/db/schemas"; @@ -64,7 +63,6 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) => response: { 200: SecretSharingSchema.pick({ encryptedValue: true, - password: true, iv: true, tag: true, expiresAt: true, @@ -81,12 +79,14 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) => hashedHex: req.query.hashedHex, orgId: req.permission?.orgId }); - if (!sharedSecret) return undefined; + + // only return secret if it exists and has no password set + if (!sharedSecret || sharedSecret.password) return undefined; + return { encryptedValue: sharedSecret.encryptedValue, iv: sharedSecret.iv, tag: sharedSecret.tag, - password: sharedSecret.password, expiresAt: sharedSecret.expiresAt, expiresAfterViews: sharedSecret.expiresAfterViews, accessType: sharedSecret.accessType, @@ -110,8 +110,15 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) => hashedHex: z.string() }), response: { - 200: z.object({ - isValid: z.boolean() + 200: SecretSharingSchema.pick({ + encryptedValue: true, + iv: true, + tag: true, + expiresAt: true, + expiresAfterViews: true, + accessType: true, + }).extend({ + orgName: z.string().optional() }) } }, @@ -119,22 +126,24 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) => const { id } = req.params; const { password, hashedHex } = req.body; - const sharedSecret = await req.server.services.secretSharing.getActiveSharedSecretById({ + const sharedSecret = await req.server.services.secretSharing.validateSecretPassword({ sharedSecretId: id, hashedHex, - orgId: req.permission?.orgId + orgId: req.permission?.orgId, + password }); - if (!sharedSecret) { - return { isValid: false }; - } + if (!sharedSecret) return undefined; - if (sharedSecret.password) { - const isMatch = await bcrypt.compare(password, sharedSecret.password); - return { isValid: isMatch }; - } - - return { isValid: false }; + return { + encryptedValue: sharedSecret.encryptedValue, + iv: sharedSecret.iv, + tag: sharedSecret.tag, + expiresAt: sharedSecret.expiresAt, + expiresAfterViews: sharedSecret.expiresAfterViews, + accessType: sharedSecret.accessType, + orgName: sharedSecret.orgName + }; } }); diff --git a/backend/src/services/secret-sharing/secret-sharing-service.ts b/backend/src/services/secret-sharing/secret-sharing-service.ts index 73a1bb6e8..2f01c6748 100644 --- a/backend/src/services/secret-sharing/secret-sharing-service.ts +++ b/backend/src/services/secret-sharing/secret-sharing-service.ts @@ -11,7 +11,8 @@ import { TCreateSharedSecretDTO, TDeleteSharedSecretDTO, TGetActiveSharedSecretByIdDTO, - TGetSharedSecretsDTO + TGetSharedSecretsDTO, + TValidateActiveSharedSecretDTO } from "./secret-sharing-types"; type TSecretSharingServiceFactoryDep = { @@ -108,8 +109,9 @@ export const secretSharingServiceFactory = ({ throw new BadRequestError({ message: "Shared secret value too long" }); } + const hashedPassword = password ? await bcrypt.hash(password, 10) : null; const newSharedSecret = await secretSharingDAL.create({ - password, + password: hashedPassword, encryptedValue, hashedHex, iv, @@ -211,6 +213,22 @@ export const secretSharingServiceFactory = ({ }; }; + const validateSecretPassword = async ({ + sharedSecretId, + hashedHex, + orgId, + password + }: TValidateActiveSharedSecretDTO) => { + const sharedSecret = await getActiveSharedSecretById({ sharedSecretId, hashedHex, orgId }); + + if (!sharedSecret || !sharedSecret.password) return undefined; + + const isMatch = await bcrypt.compare(password, sharedSecret.password); + + if (!isMatch) return undefined; + return sharedSecret + }; + const deleteSharedSecretById = async (deleteSharedSecretInput: TDeleteSharedSecretDTO) => { const { actor, actorId, orgId, actorAuthMethod, actorOrgId, sharedSecretId } = deleteSharedSecretInput; const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId); @@ -224,6 +242,7 @@ export const secretSharingServiceFactory = ({ createPublicSharedSecret, getSharedSecrets, deleteSharedSecretById, - getActiveSharedSecretById + getActiveSharedSecretById, + validateSecretPassword }; }; diff --git a/backend/src/services/secret-sharing/secret-sharing-types.ts b/backend/src/services/secret-sharing/secret-sharing-types.ts index 16a89077a..e96a68e64 100644 --- a/backend/src/services/secret-sharing/secret-sharing-types.ts +++ b/backend/src/services/secret-sharing/secret-sharing-types.ts @@ -35,6 +35,10 @@ export type TGetActiveSharedSecretByIdDTO = { orgId?: string; }; +export type TValidateActiveSharedSecretDTO = TGetActiveSharedSecretByIdDTO & { + password: string; +}; + export type TCreateSharedSecretDTO = TSharedSecretPermission & TCreatePublicSharedSecretDTO; export type TDeleteSharedSecretDTO = {