import * as jose from "https://deno.land/x/jose@v5.9.6/index.ts"; import { getUserByEmail } from "./supabase.ts"; import { SupabaseClient } from "@supabase/supabase-js"; import crypto from "node:crypto"; import { Buffer } from "node:buffer"; export const authenticateUser = async ( supabaseClient: SupabaseClient, authToken: string, ): Promise => { try { const jwtSecret = Deno.env.get("JWT_SECRET_KEY"); if (!jwtSecret) throw new Error("JWT_SECRET_KEY not configured"); const secretBytes = new TextEncoder().encode(jwtSecret); const payload = await jose.jwtVerify(authToken, secretBytes); const { payload: { email } } = payload; const user = await getUserByEmail(supabaseClient, email as string); return user; } catch (error: any) { throw new Error(error.message || "Failed to authenticate user"); } }; /** * Decrypts an encrypted secret with the same master encryption key. * @param encryptedData - base64 string from the database * @param iv - base64 IV from the database * @param masterKey - 32-byte string or buffer * @returns the original plaintext secret */ export function decryptSecret( encryptedData: string, iv: string, masterKey: string, ) { // Decode the base64 master key const decodedKey = Buffer.from(masterKey, "base64"); if (decodedKey.length !== 32) { throw new Error( "ENCRYPTION_KEY must be 32 bytes when decoded from base64.", ); } const decipher = crypto.createDecipheriv( "aes-256-cbc", decodedKey, // Use the decoded key instead of raw masterKey Buffer.from(iv, "base64"), ); let decrypted = decipher.update(encryptedData, "base64", "utf8"); decrypted += decipher.final("utf8"); return decrypted; }