diff --git a/pages/mitgliederbereich/profil.vue b/pages/mitgliederbereich/profil.vue index 43441ec..e1f2061 100644 --- a/pages/mitgliederbereich/profil.vue +++ b/pages/mitgliederbereich/profil.vue @@ -393,6 +393,12 @@ const loadPasskeys = async () => { } } +const isFirefoxBrowser = () => { + if (!process.client) return false + const ua = navigator.userAgent || '' + return /firefox/i.test(ua) +} + const addPasskey = async () => { passkeyError.value = '' passkeyLoading.value = true @@ -400,13 +406,15 @@ const addPasskey = async () => { const name = window.prompt('Name für den Passkey (z.B. "iPhone", "Laptop"):', 'Passkey') || 'Passkey' const mod = await import('@simplewebauthn/browser') -// Kein preferredAuthenticatorType setzen → kein authenticatorAttachment gesetzt - // → Browser (inkl. Firefox) wählt selbst: interner Passkey-Store, Smartphone oder Security Key - // Firefox speichert den Passkey dann intern wie ein Passwort (kein Hardware-Key nötig) - const res = await $fetch('/api/auth/passkeys/registration-options', { method: 'POST' }) + // Firefox/Linux kommt mit localDevice teils nicht klar. Für Chromium bevorzugen wir lokal. + const registrationOptionsRequest = isFirefoxBrowser() + ? { method: 'POST' } + : { method: 'POST', body: { preferredAuthenticatorType: 'localDevice' } } - // @simplewebauthn/browser v13+ erwartet { optionsJSON: options } - const credential = await mod.startRegistration({ optionsJSON: res.options }) + const res = await $fetch('/api/auth/passkeys/registration-options', registrationOptionsRequest) + + // @simplewebauthn/browser v13+ erwartet { optionsJSON: options } + const credential = await mod.startRegistration({ optionsJSON: res.options }) await $fetch('/api/auth/passkeys/register', { method: 'POST',