Add debug information display for passkey registration process
Some checks failed
Code Analysis (JS/Vue) / analyze (push) Failing after 49s
Some checks failed
Code Analysis (JS/Vue) / analyze (push) Failing after 49s
Introduce a debug information section in the passkey registration flow, providing insights into the challenge, RP-ID, and origin when debugging is enabled. Enhance logging to capture detailed options and cross-device authentication information, improving troubleshooting capabilities and user guidance during the registration process.
This commit is contained in:
@@ -166,6 +166,23 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Debug Info (nur bei Passkey-Registrierung) -->
|
||||
<div
|
||||
v-if="usePasskey && showDebugInfo && debugChallenge"
|
||||
class="bg-blue-50 border border-blue-200 rounded-lg p-4 text-xs"
|
||||
>
|
||||
<div class="font-semibold text-blue-900 mb-2">🔍 Debug-Informationen (QR-Code):</div>
|
||||
<div class="space-y-1 text-blue-800">
|
||||
<div><strong>Challenge:</strong> <code class="bg-blue-100 px-1 rounded">{{ debugChallenge.substring(0, 40) }}...</code></div>
|
||||
<div><strong>RP-ID:</strong> <code class="bg-blue-100 px-1 rounded">{{ debugRpId }}</code></div>
|
||||
<div><strong>Origin:</strong> <code class="bg-blue-100 px-1 rounded">{{ window.location.origin }}</code></div>
|
||||
<div class="mt-2 text-blue-700">
|
||||
<strong>Hinweis:</strong> Der QR-Code wird vom Browser generiert.
|
||||
Prüfe in der Browser-Konsole (F12) für vollständige Debug-Ausgaben.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<button
|
||||
type="submit"
|
||||
@@ -226,6 +243,9 @@ const usePasskey = ref(false)
|
||||
const isPasskeySupported = ref(false)
|
||||
const passkeySupportReason = ref('')
|
||||
const setPasswordForPasskey = ref(true)
|
||||
const showDebugInfo = ref(false)
|
||||
const debugChallenge = ref('')
|
||||
const debugRpId = ref('')
|
||||
|
||||
onMounted(() => {
|
||||
try {
|
||||
@@ -384,6 +404,63 @@ const handleRegisterWithPasskey = async () => {
|
||||
}
|
||||
|
||||
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))
|
||||
console.log('[DEBUG] Options summary for startRegistration:', {
|
||||
challenge: pre.options?.challenge ? 'present' : 'missing',
|
||||
challengeValue: pre.options?.challenge ? pre.options.challenge.substring(0, 20) + '...' : 'missing',
|
||||
rp: pre.options?.rp,
|
||||
rpId: pre.options?.rp?.id,
|
||||
rpName: pre.options?.rp?.name,
|
||||
user: pre.options?.user,
|
||||
userName: pre.options?.user?.name,
|
||||
userDisplayName: pre.options?.user?.displayName,
|
||||
timeout: pre.options?.timeout,
|
||||
timeoutSeconds: pre.options?.timeout ? Math.round(pre.options.timeout / 1000) : 'default',
|
||||
pubKeyCredParams: pre.options?.pubKeyCredParams?.length,
|
||||
authenticatorSelection: pre.options?.authenticatorSelection,
|
||||
excludeCredentials: pre.options?.excludeCredentials?.length || 0
|
||||
})
|
||||
|
||||
// Vollständige Options für QR-Code-Debug (wird im QR-Code kodiert)
|
||||
console.log('[DEBUG] Full options object (encoded in QR code for Cross-Device):', JSON.stringify(pre.options, null, 2))
|
||||
|
||||
// Prüfe, ob Cross-Device-Authentifizierung verwendet wird
|
||||
console.log('[DEBUG] Cross-Device Info (QR-Code sollte zu dieser URL führen):', {
|
||||
isSecureContext: window.isSecureContext,
|
||||
origin: window.location.origin,
|
||||
protocol: window.location.protocol,
|
||||
hostname: window.location.hostname,
|
||||
port: window.location.port || 'default (443 for HTTPS)',
|
||||
fullUrl: window.location.href,
|
||||
// Der QR-Code sollte zur aktuellen Origin führen
|
||||
qrCodeShouldPointTo: window.location.origin,
|
||||
// Prüfe, ob die Options die richtige Origin enthalten
|
||||
optionsRpId: pre.options?.rp?.id,
|
||||
optionsMatchesOrigin: pre.options?.rp?.id === window.location.hostname
|
||||
})
|
||||
|
||||
// QR-Code-Debug: Die Challenge ist Teil der WebAuthn-Request
|
||||
// Der Browser generiert automatisch einen QR-Code für Cross-Device
|
||||
debugChallenge.value = pre.options?.challenge || ''
|
||||
debugRpId.value = pre.options?.rp?.id || ''
|
||||
showDebugInfo.value = true
|
||||
|
||||
console.log('[DEBUG] QR-Code Info (for Cross-Device):', {
|
||||
challenge: pre.options?.challenge,
|
||||
challengeLength: pre.options?.challenge?.length,
|
||||
rpId: pre.options?.rp?.id,
|
||||
expectedOrigin: window.location.origin,
|
||||
currentURL: window.location.href,
|
||||
isHTTPS: window.location.protocol === 'https:',
|
||||
note: 'Der QR-Code wird vom Browser generiert und enthält die Challenge + Server-Info'
|
||||
})
|
||||
|
||||
// Prüfe, ob die Origin korrekt ist
|
||||
if (window.location.origin.includes(':3100')) {
|
||||
console.error('[DEBUG] WARNING: Current origin contains port 3100!', window.location.origin)
|
||||
console.error('[DEBUG] This might cause Cross-Device authentication to fail.')
|
||||
}
|
||||
|
||||
const webauthnStart = Date.now()
|
||||
|
||||
const mod = await import('@simplewebauthn/browser')
|
||||
@@ -391,23 +468,45 @@ const handleRegisterWithPasskey = async () => {
|
||||
// @simplewebauthn/browser v13+ erwartet die Options direkt
|
||||
let credential
|
||||
try {
|
||||
// Timeout-Warnung nach 2 Minuten
|
||||
const timeoutWarning = setTimeout(() => {
|
||||
console.warn('[DEBUG] startRegistration still waiting after 2 minutes. This might be a Cross-Device timeout.')
|
||||
console.warn('[DEBUG] Make sure your smartphone can reach the server and CORS is configured correctly.')
|
||||
console.warn('[DEBUG] Current origin:', window.location.origin)
|
||||
console.warn('[DEBUG] Challenge:', pre.options?.challenge)
|
||||
}, 120000)
|
||||
|
||||
console.log('[DEBUG] startRegistration called - QR-Code should appear now (if Cross-Device)')
|
||||
credential = await mod.startRegistration(pre.options)
|
||||
|
||||
clearTimeout(timeoutWarning)
|
||||
|
||||
const webauthnDuration = Date.now() - webauthnStart
|
||||
console.log(`[DEBUG] startRegistration completed (${webauthnDuration}ms)`, {
|
||||
hasCredential: !!credential,
|
||||
credentialId: credential?.id,
|
||||
responseType: credential?.response?.constructor?.name,
|
||||
transports: credential?.transports
|
||||
transports: credential?.transports,
|
||||
durationSeconds: Math.round(webauthnDuration / 1000)
|
||||
})
|
||||
} catch (webauthnError) {
|
||||
const webauthnDuration = Date.now() - webauthnStart
|
||||
console.error(`[DEBUG] WebAuthn startRegistration failed (${webauthnDuration}ms):`, {
|
||||
console.error(`[DEBUG] WebAuthn startRegistration failed (${webauthnDuration}ms / ${Math.round(webauthnDuration / 1000)}s):`, {
|
||||
error: webauthnError,
|
||||
message: webauthnError?.message,
|
||||
name: webauthnError?.name,
|
||||
code: webauthnError?.code,
|
||||
stack: webauthnError?.stack
|
||||
})
|
||||
throw new Error('Passkey-Registrierung fehlgeschlagen: ' + (webauthnError?.message || 'Unbekannter Fehler'))
|
||||
|
||||
// Spezifische Fehlermeldungen für häufige Probleme
|
||||
if (webauthnError?.message?.includes('timeout') || webauthnDuration > 290000) {
|
||||
throw new Error('Passkey-Registrierung: Timeout. Bitte stellen Sie sicher, dass Ihr Smartphone eine Internetverbindung hat und die Website über HTTPS erreichbar ist.')
|
||||
} else if (webauthnError?.message?.includes('NotAllowedError') || webauthnError?.name === 'NotAllowedError') {
|
||||
throw new Error('Passkey-Registrierung abgebrochen oder nicht erlaubt.')
|
||||
} else {
|
||||
throw new Error('Passkey-Registrierung fehlgeschlagen: ' + (webauthnError?.message || 'Unbekannter Fehler'))
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[DEBUG] Sending credential to server...')
|
||||
|
||||
Reference in New Issue
Block a user