Some checks failed
Code Analysis (JS/Vue) / analyze (push) Failing after 49s
Add validation for server response in the registration process, ensuring the presence of necessary options. Implement CORS headers for cross-device authentication and increase the timeout for registration to 5 minutes. Include debug logging for options structure to aid in troubleshooting.
84 lines
2.6 KiB
JavaScript
84 lines
2.6 KiB
JavaScript
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'
|
|
},
|
|
// Timeout erhöhen für Cross-Device (Standard: 60s, hier: 5 Minuten)
|
|
timeout: 300000
|
|
})
|
|
|
|
setPreRegistration(registrationId, {
|
|
challenge: options.challenge,
|
|
userId,
|
|
name,
|
|
email,
|
|
phone
|
|
})
|
|
|
|
await writeAuditLog('auth.passkey.prereg.options', { email })
|
|
|
|
// CORS-Header für Cross-Device Authentication
|
|
const requestOrigin = getHeader(event, 'origin')
|
|
if (requestOrigin) {
|
|
setHeader(event, 'Access-Control-Allow-Origin', requestOrigin)
|
|
setHeader(event, 'Access-Control-Allow-Credentials', 'true')
|
|
setHeader(event, 'Access-Control-Allow-Methods', 'POST, OPTIONS')
|
|
setHeader(event, 'Access-Control-Allow-Headers', 'Content-Type, Authorization')
|
|
}
|
|
|
|
if (getMethod(event) === 'OPTIONS') {
|
|
return { success: true }
|
|
}
|
|
|
|
// Debug: Log Options-Struktur
|
|
console.log('[WebAuthn Pre-Registration Options]', {
|
|
hasChallenge: !!options.challenge,
|
|
rpId: options.rp?.id,
|
|
userId: options.user?.id ? 'present' : 'missing',
|
|
timeout: options.timeout
|
|
})
|
|
|
|
return { success: true, registrationId, options }
|
|
})
|
|
|