import { NextResponse } from "next/server"; import { generateRegistrationOptions } from "@simplewebauthn/server"; import type { AuthenticatorTransportFuture } from "@simplewebauthn/server"; import { query } from "@/lib/db"; import { requireSession, UnauthorizedError } from "@/lib/auth/session"; import { rpID, rpName } from "@/lib/auth/webauthn-config"; import { storeChallenge } from "@/lib/auth/webauthn-challenges"; export async function POST() { try { const session = await requireSession(); const existing = await query<{ credential_id: string; transports: AuthenticatorTransportFuture[]; }>("select credential_id, transports from passkey_credentials where user_id = $1", [ session.user.id, ]); const options = await generateRegistrationOptions({ rpName: rpName(), rpID: rpID(), userID: new TextEncoder().encode(session.user.id), userName: session.user.email, userDisplayName: session.user.full_name || session.user.email, attestationType: "none", excludeCredentials: existing.map((c) => ({ id: c.credential_id, transports: c.transports, })), authenticatorSelection: { residentKey: "preferred", userVerification: "preferred", }, }); await storeChallenge(options.challenge, "registration", session.user.id); return NextResponse.json(options); } catch (err) { if (err instanceof UnauthorizedError) { return NextResponse.json({ error: "unauthorized" }, { status: 401 }); } throw err; } }