Implement passkey recovery feature, including email link requests and registration options. Update login and registration pages to support passkey authentication, with UI enhancements for user experience. Add server-side handling for passkey registration and login, including account activation checks. Update environment configuration for passkey recovery TTL settings.
Some checks failed
Code Analysis (JS/Vue) / analyze (push) Failing after 48s
Some checks failed
Code Analysis (JS/Vue) / analyze (push) Failing after 48s
This commit is contained in:
60
server/api/auth/register-passkey-options.post.js
Normal file
60
server/api/auth/register-passkey-options.post.js
Normal file
@@ -0,0 +1,60 @@
|
||||
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 }
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user