import crypto from 'crypto' import { generateRegistrationOptions } from '@simplewebauthn/server' import { readUsers } from '../../utils/auth.js' import { getWebAuthnConfig } from '../../utils/webauthn-config.js' import { setPreRegistration } from '../../utils/webauthn-challenges.js' import { writeAuditLog } from '../../utils/audit-log.js' function isValidEmail(email) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(email || '')) } export default defineEventHandler(async (event) => { const body = await readBody(event) const name = String(body?.name || '').trim() const email = String(body?.email || '').trim().toLowerCase() const phone = String(body?.phone || '').trim() if (!name || !email) { throw createError({ statusCode: 400, message: 'Name und E-Mail sind erforderlich' }) } if (!isValidEmail(email)) { throw createError({ statusCode: 400, message: 'Ungültige E-Mail-Adresse' }) } const users = await readUsers() if (users.some(u => String(u.email || '').toLowerCase() === email)) { throw createError({ statusCode: 409, message: 'Ein Benutzer mit dieser E-Mail-Adresse existiert bereits' }) } const { rpId, rpName } = getWebAuthnConfig() const userId = crypto.randomUUID() const registrationId = crypto.randomBytes(16).toString('hex') const options = await generateRegistrationOptions({ rpName, rpID: rpId, userID: new TextEncoder().encode(String(userId)), userName: email, userDisplayName: name, attestationType: 'none', authenticatorSelection: { residentKey: 'preferred', userVerification: 'preferred' } }) setPreRegistration(registrationId, { challenge: options.challenge, userId, name, email, phone }) await writeAuditLog('auth.passkey.prereg.options', { email }) return { success: true, registrationId, options } })