Update Passkey Registration to comply with @simplewebauthn/browser v13+ API
Some checks failed
Code Analysis (JS/Vue) / analyze (push) Failing after 49s
Some checks failed
Code Analysis (JS/Vue) / analyze (push) Failing after 49s
Refactor the Passkey registration logic in multiple components to utilize the new API structure requiring { optionsJSON: options }. Enhance debug logging to validate options, including checks for user ID format and challenge type. This update aims to improve compliance with the latest library requirements and provide better insights during the registration process.
This commit is contained in:
@@ -319,7 +319,8 @@ const addPasskey = async () => {
|
||||
const name = window.prompt('Name für den Passkey (z.B. "iPhone", "Laptop"):', 'Passkey') || 'Passkey'
|
||||
const res = await $fetch('/api/auth/passkeys/registration-options', { method: 'POST' })
|
||||
const mod = await import('@simplewebauthn/browser')
|
||||
const credential = await mod.startRegistration(res.options)
|
||||
// @simplewebauthn/browser v13+ erwartet { optionsJSON: options }
|
||||
const credential = await mod.startRegistration({ optionsJSON: res.options })
|
||||
await $fetch('/api/auth/passkeys/register', {
|
||||
method: 'POST',
|
||||
body: { credential, name }
|
||||
|
||||
@@ -167,7 +167,8 @@ const addPasskeyViaToken = async () => {
|
||||
})
|
||||
|
||||
const mod = await import('@simplewebauthn/browser')
|
||||
const credential = await mod.startRegistration(opts.options)
|
||||
// @simplewebauthn/browser v13+ erwartet { optionsJSON: options }
|
||||
const credential = await mod.startRegistration({ optionsJSON: opts.options })
|
||||
|
||||
const res = await $fetch('/api/auth/passkeys/recovery/complete', {
|
||||
method: 'POST',
|
||||
|
||||
@@ -445,26 +445,44 @@ const handleRegisterWithPasskey = async () => {
|
||||
}
|
||||
|
||||
// Debug: Prüfe die vollständige Options-Struktur
|
||||
// WICHTIG: @simplewebauthn/browser erwartet:
|
||||
// - challenge: Base64URL-String
|
||||
// - user.id: Base64URL-String (wird automatisch zu Uint8Array konvertiert)
|
||||
// - excludeCredentials[].id: Base64URL-String (wird automatisch zu Uint8Array konvertiert)
|
||||
console.log('[DEBUG] Full options structure check:', {
|
||||
hasChallenge: !!pre.options.challenge,
|
||||
challengeValue: pre.options.challenge?.substring(0, 20) + '...',
|
||||
challengeType: typeof pre.options.challenge,
|
||||
challengeLength: pre.options.challenge?.length,
|
||||
hasRp: !!pre.options.rp,
|
||||
rpId: pre.options.rp?.id,
|
||||
rpName: pre.options.rp?.name,
|
||||
hasUser: !!pre.options.user,
|
||||
userId: pre.options.user?.id ? 'present' : 'missing',
|
||||
userIdType: typeof pre.options.user?.id,
|
||||
userIdValue: typeof pre.options.user?.id === 'string' ? pre.options.user.id.substring(0, 20) + '...' : 'not a string',
|
||||
userName: pre.options.user?.name,
|
||||
userDisplayName: pre.options.user?.displayName,
|
||||
hasPubKeyCredParams: !!pre.options.pubKeyCredParams,
|
||||
pubKeyCredParamsCount: pre.options.pubKeyCredParams?.length,
|
||||
hasAuthenticatorSelection: !!pre.options.authenticatorSelection,
|
||||
authenticatorSelection: pre.options.authenticatorSelection,
|
||||
timeout: pre.options.timeout,
|
||||
timeoutType: typeof pre.options.timeout,
|
||||
excludeCredentialsCount: pre.options.excludeCredentials?.length || 0,
|
||||
hasExtensions: !!pre.options.extensions,
|
||||
hasHints: !!pre.options.hints,
|
||||
allKeys: Object.keys(pre.options),
|
||||
optionsStringified: JSON.stringify(pre.options).substring(0, 200) + '...'
|
||||
userKeys: pre.options.user ? Object.keys(pre.options.user) : []
|
||||
})
|
||||
|
||||
// Prüfe, ob user.id ein String ist (Base64URL)
|
||||
// @simplewebauthn/browser erwartet user.id als Base64URL-String
|
||||
if (pre.options.user?.id && typeof pre.options.user.id !== 'string') {
|
||||
console.error('[DEBUG] ERROR: user.id is not a string!', typeof pre.options.user.id, pre.options.user.id)
|
||||
console.error('[DEBUG] @simplewebauthn/browser erwartet user.id als Base64URL-String')
|
||||
throw new Error('Invalid user.id format - must be Base64URL string')
|
||||
}
|
||||
|
||||
console.log('[DEBUG] Calling startRegistration...')
|
||||
console.log('[DEBUG] Full options object (will be encoded in QR code for Cross-Device):', JSON.stringify(pre.options, null, 2))
|
||||
@@ -526,8 +544,20 @@ const handleRegisterWithPasskey = async () => {
|
||||
|
||||
const webauthnStart = Date.now()
|
||||
|
||||
// Importiere @simplewebauthn/browser
|
||||
const mod = await import('@simplewebauthn/browser')
|
||||
// startRegistration erwartet die Options direkt (wie in anderen Dateien auch)
|
||||
|
||||
// Prüfe, ob startRegistration verfügbar ist
|
||||
if (!mod.startRegistration) {
|
||||
console.error('[DEBUG] ERROR: mod.startRegistration is not available!')
|
||||
console.error('[DEBUG] Available exports:', Object.keys(mod))
|
||||
throw new Error('startRegistration ist nicht verfügbar. Bitte prüfen Sie, ob @simplewebauthn/browser korrekt installiert ist.')
|
||||
}
|
||||
|
||||
console.log('[DEBUG] @simplewebauthn/browser imported successfully')
|
||||
console.log('[DEBUG] Available exports:', Object.keys(mod))
|
||||
console.log('[DEBUG] startRegistration type:', typeof mod.startRegistration)
|
||||
|
||||
let credential
|
||||
try {
|
||||
// Timeout-Warnung nach 2 Minuten
|
||||
@@ -563,24 +593,44 @@ const handleRegisterWithPasskey = async () => {
|
||||
console.log('[DEBUG] Options validation before startRegistration:', {
|
||||
hasChallenge: !!pre.options.challenge,
|
||||
challengeType: typeof pre.options.challenge,
|
||||
challengeValue: pre.options.challenge?.substring(0, 20) + '...',
|
||||
hasRp: !!pre.options.rp,
|
||||
hasRpId: !!pre.options.rp?.id,
|
||||
hasUser: !!pre.options.user,
|
||||
hasUserID: !!pre.options.user?.id,
|
||||
userIdType: typeof pre.options.user?.id,
|
||||
userIdValue: typeof pre.options.user?.id === 'string' ? pre.options.user.id.substring(0, 20) + '...' : 'not a string',
|
||||
timeout: pre.options.timeout,
|
||||
timeoutType: typeof pre.options.timeout,
|
||||
allKeys: Object.keys(pre.options)
|
||||
allKeys: Object.keys(pre.options),
|
||||
userKeys: pre.options.user ? Object.keys(pre.options.user) : []
|
||||
})
|
||||
|
||||
// Stelle sicher, dass challenge ein String ist (nicht Base64URL-encoded)
|
||||
// Stelle sicher, dass challenge ein String ist (Base64URL)
|
||||
if (typeof pre.options.challenge !== 'string') {
|
||||
console.error('[DEBUG] ERROR: Challenge is not a string!', pre.options.challenge)
|
||||
console.error('[DEBUG] ERROR: Challenge is not a string!', typeof pre.options.challenge, pre.options.challenge)
|
||||
throw new Error('Invalid challenge format')
|
||||
}
|
||||
|
||||
// Direkt die Options übergeben (wie in profil.vue und passkey-wiederherstellen.vue)
|
||||
// @simplewebauthn/browser v13+ erwartet die Options direkt
|
||||
credential = await mod.startRegistration(pre.options)
|
||||
// Prüfe user.id - sollte ein String (Base64URL) sein
|
||||
if (pre.options.user?.id && typeof pre.options.user.id !== 'string') {
|
||||
console.warn('[DEBUG] WARNING: user.id is not a string!', typeof pre.options.user.id, pre.options.user.id)
|
||||
console.warn('[DEBUG] @simplewebauthn/browser erwartet user.id als Base64URL-String')
|
||||
}
|
||||
|
||||
// @simplewebauthn/browser v13+ erwartet { optionsJSON: options }
|
||||
// Die Bibliothek unterstützt auch die alte API (direkt options), gibt aber eine Warnung
|
||||
// Wir verwenden die neue API-Struktur, um die Warnung zu vermeiden
|
||||
console.log('[DEBUG] Calling mod.startRegistration with new API structure...')
|
||||
console.log('[DEBUG] Options structure:', {
|
||||
challenge: pre.options.challenge?.substring(0, 20) + '...',
|
||||
rpId: pre.options.rp?.id,
|
||||
userId: typeof pre.options.user?.id === 'string' ? pre.options.user.id.substring(0, 20) + '...' : pre.options.user?.id,
|
||||
timeout: pre.options.timeout
|
||||
})
|
||||
|
||||
// Neue API-Struktur: { optionsJSON: options }
|
||||
credential = await mod.startRegistration({ optionsJSON: pre.options })
|
||||
|
||||
clearTimeout(timeoutWarning)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user