85 lines
2.5 KiB
TypeScript
85 lines
2.5 KiB
TypeScript
/**
|
|
* Internal API to get decrypted key value
|
|
* This endpoint is used by Vibn internally, not exposed to frontend
|
|
*/
|
|
|
|
import { NextResponse } from 'next/server';
|
|
import { getAdminAuth, getAdminDb } from '@/lib/firebase/admin';
|
|
import { FieldValue } from 'firebase-admin/firestore';
|
|
import * as crypto from 'crypto';
|
|
|
|
const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY || 'vibn-default-encryption-key-change-me!!';
|
|
const ALGORITHM = 'aes-256-cbc';
|
|
|
|
function decrypt(encrypted: string, ivHex: string): string {
|
|
const key = crypto.createHash('sha256').update(ENCRYPTION_KEY).digest();
|
|
const iv = Buffer.from(ivHex, 'hex');
|
|
const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
|
|
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
|
|
decrypted += decipher.final('utf8');
|
|
return decrypted;
|
|
}
|
|
|
|
export async function POST(request: Request) {
|
|
try {
|
|
const authHeader = request.headers.get('Authorization');
|
|
if (!authHeader?.startsWith('Bearer ')) {
|
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
|
}
|
|
|
|
const idToken = authHeader.split('Bearer ')[1];
|
|
const adminAuth = getAdminAuth();
|
|
const adminDb = getAdminDb();
|
|
|
|
let userId: string;
|
|
try {
|
|
const decodedToken = await adminAuth.verifyIdToken(idToken);
|
|
userId = decodedToken.uid;
|
|
} catch (error) {
|
|
return NextResponse.json({ error: 'Invalid token' }, { status: 401 });
|
|
}
|
|
|
|
const { service } = await request.json();
|
|
|
|
if (!service) {
|
|
return NextResponse.json({ error: 'Service is required' }, { status: 400 });
|
|
}
|
|
|
|
// Get the key
|
|
const keysSnapshot = await adminDb
|
|
.collection('userKeys')
|
|
.where('userId', '==', userId)
|
|
.where('service', '==', service)
|
|
.limit(1)
|
|
.get();
|
|
|
|
if (keysSnapshot.empty) {
|
|
return NextResponse.json({ error: 'Key not found', hasKey: false }, { status: 404 });
|
|
}
|
|
|
|
const keyDoc = keysSnapshot.docs[0];
|
|
const keyData = keyDoc.data();
|
|
|
|
// Decrypt the key
|
|
const decryptedKey = decrypt(keyData.encryptedKey, keyData.iv);
|
|
|
|
// Update last used timestamp
|
|
await keyDoc.ref.update({
|
|
lastUsed: FieldValue.serverTimestamp(),
|
|
});
|
|
|
|
return NextResponse.json({
|
|
hasKey: true,
|
|
keyValue: decryptedKey,
|
|
service: keyData.service,
|
|
});
|
|
} catch (error) {
|
|
console.error('Error getting key:', error);
|
|
return NextResponse.json(
|
|
{ error: 'Failed to get key', details: error instanceof Error ? error.message : String(error) },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|
|
|