Files
multiverse/jumpa-iam/app/api/auth/qr-auth/route.ts
T

65 lines
1.9 KiB
TypeScript

import { NextResponse } from 'next/server';
import crypto from 'crypto';
import jwt from 'jsonwebtoken';
import { db } from "@/drizzle/db";
import { users } from "@/drizzle/schema";
import { eq } from 'drizzle-orm';
export async function POST(req: Request) {
try {
const { sessionId, signature, email } = await req.json();
// TAHAP NANO: Validasi Kriptografis Challenge QR Code
if (!sessionId || !signature || !email) {
return NextResponse.json({ error: 'Missing challenge parameters' }, { status: 400 });
}
// Server memverifikasi bahwa signature adalah hash dari sessionId + email + secret
const expectedSignature = crypto
.createHmac('sha256', process.env.JWT_SECRET as string)
.update(`${sessionId}:${email}`)
.digest('hex');
if (signature !== expectedSignature) {
return NextResponse.json({ error: 'Invalid QR cryptographic signature' }, { status: 401 });
}
// Verifikasi berhasil, generate real JWT token
const userResult = await db.select().from(users).where(eq(users.email, email)).limit(1);
if (userResult.length === 0) {
return NextResponse.json({ error: 'User not found' }, { status: 404 });
}
const user = userResult[0];
const token = jwt.sign(
{
id: user.id,
email: user.email,
role: user.role,
tenantId: user.tenantId,
},
process.env.JWT_SECRET as string,
{ expiresIn: '8h' }
);
const response = NextResponse.json({ message: 'QR Auth Berhasil' });
response.cookies.set({
name: 'jumpa_token',
value: token,
httpOnly: true,
secure: true,
sameSite: 'lax',
path: '/',
domain: process.env.NEXT_PUBLIC_COOKIE_DOMAIN || undefined,
maxAge: 8 * 60 * 60
});
return response;
} catch (e) {
console.error("QR Auth Verify Error:", e);
return NextResponse.json({ error: 'Server error' }, { status: 500 });
}
}