|
|
|
|
@@ -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)
|
|
|
|
|
|
|
|
|
|
|