Files
harheimertc/server/api/auth/passkeys/authentication-options.post.js
Torsten Schulz (local) 9def0fdc32
Some checks failed
Code Analysis and Production Deploy / analyze (push) Failing after 2m50s
Code Analysis and Production Deploy / deploy-production (push) Has been skipped
Code Analysis and Production Deploy / deploy-test (push) Has been skipped
chore(lint): add safe fallbacks for Nitro globals (getMethod/getRequestURL) in passkey and middleware handlers
2026-05-27 20:02:46 +02:00

58 lines
2.0 KiB
JavaScript

import { generateAuthenticationOptions } from '@simplewebauthn/server'
import { readUsers } from '../../../utils/auth.js'
import { getWebAuthnConfig } from '../../../utils/webauthn-config.js'
import { setAuthChallenge } from '../../../utils/webauthn-challenges.js'
export default defineEventHandler(async (event) => {
// CORS-Header für Cross-Device Authentication
const origin = getHeader(event, 'origin')
if (origin) {
setHeader(event, 'Access-Control-Allow-Origin', origin)
setHeader(event, 'Access-Control-Allow-Credentials', 'true')
setHeader(event, 'Access-Control-Allow-Methods', 'POST, OPTIONS')
setHeader(event, 'Access-Control-Allow-Headers', 'Content-Type, Authorization')
}
// Provide a safe fallback for getMethod when linting/runtime doesn't expose it
const _getMethod = typeof globalThis.getMethod === 'function' ? globalThis.getMethod : (e) => (e?.req?.method || e?.method || 'GET')
if (_getMethod(event) === 'OPTIONS') {
return { success: true }
}
const body = await readBody(event)
const email = String(body?.email || '').trim().toLowerCase()
const { rpId } = getWebAuthnConfig()
let allowCredentials
if (email) {
const users = await readUsers()
const user = users.find(u => String(u.email || '').toLowerCase() === email)
const passkeys = Array.isArray(user?.passkeys) ? user.passkeys : []
allowCredentials = passkeys
.filter(pk => pk?.credentialId)
.map(pk => ({
id: pk.credentialId,
type: 'public-key',
transports: pk.transports || undefined
}))
}
// Ohne E-Mail: discoverable Credentials (username-less).
// Mit E-Mail: allowCredentials nutzen, damit auch nicht-discoverable Credentials funktionieren.
const options = await generateAuthenticationOptions({
rpID: rpId,
allowCredentials,
userVerification: 'preferred',
// Timeout erhöhen für Cross-Device (Standard: 60s, hier: 5 Minuten)
timeout: 300000
})
setAuthChallenge(options.challenge)
return { success: true, options }
})