Enhance logging for mobile requests in log-requests middleware
Some checks failed
Code Analysis (JS/Vue) / analyze (push) Failing after 44s
Some checks failed
Code Analysis (JS/Vue) / analyze (push) Failing after 44s
Add functionality to log all requests from mobile devices, improving debugging capabilities. Extend the existing passkey endpoint checks to include a new endpoint for cross-device registration. This update aims to provide clearer insights into mobile user interactions with the application.
This commit is contained in:
142
pages/passkey-register-cross-device.vue
Normal file
142
pages/passkey-register-cross-device.vue
Normal file
@@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<div class="min-h-screen bg-gray-900 text-white flex items-center justify-center p-4">
|
||||
<div class="max-w-md w-full bg-gray-800 rounded-lg p-6 space-y-4">
|
||||
<h1 class="text-2xl font-bold text-center">Passkey-Registrierung</h1>
|
||||
|
||||
<div v-if="status === 'loading'" class="text-center">
|
||||
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-white mx-auto mb-4"></div>
|
||||
<p>Lade Registrierungsoptionen...</p>
|
||||
</div>
|
||||
|
||||
<div v-else-if="status === 'waiting'" class="text-center">
|
||||
<div class="animate-pulse text-4xl mb-4">🔐</div>
|
||||
<p class="text-lg mb-2">Warte auf Passkey-Authentifizierung...</p>
|
||||
<p class="text-sm text-gray-400">Bitte bestätigen Sie die Registrierung auf diesem Gerät.</p>
|
||||
</div>
|
||||
|
||||
<div v-else-if="status === 'error'" class="text-center text-red-400">
|
||||
<p class="text-lg font-semibold mb-2">Fehler</p>
|
||||
<p>{{ errorMessage }}</p>
|
||||
<button
|
||||
@click="retry"
|
||||
class="mt-4 px-4 py-2 bg-primary-600 hover:bg-primary-700 rounded"
|
||||
>
|
||||
Erneut versuchen
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-else-if="status === 'success'" class="text-center text-green-400">
|
||||
<p class="text-lg font-semibold mb-2">✅ Erfolgreich!</p>
|
||||
<p>Die Credential-Response wurde an den Desktop-Browser gesendet.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
|
||||
const status = ref('loading')
|
||||
const errorMessage = ref('')
|
||||
const registrationId = ref('')
|
||||
|
||||
// Hole registrationId aus URL-Parameter
|
||||
onMounted(async () => {
|
||||
const route = useRoute()
|
||||
registrationId.value = route.query.registrationId || ''
|
||||
|
||||
if (!registrationId.value) {
|
||||
status.value = 'error'
|
||||
errorMessage.value = 'Keine registrationId in der URL gefunden.'
|
||||
return
|
||||
}
|
||||
|
||||
await startRegistration()
|
||||
})
|
||||
|
||||
async function startRegistration() {
|
||||
try {
|
||||
status.value = 'loading'
|
||||
|
||||
// Hole Options vom Server
|
||||
console.log('[DEBUG] Fetching options for registrationId:', registrationId.value)
|
||||
const optionsResponse = await fetch(`/api/auth/register-passkey-options/${registrationId.value}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
|
||||
if (!optionsResponse.ok) {
|
||||
throw new Error(`Options request failed: ${optionsResponse.status}`)
|
||||
}
|
||||
|
||||
const optionsData = await optionsResponse.json()
|
||||
|
||||
if (!optionsData.success || !optionsData.options) {
|
||||
throw new Error('Invalid options response')
|
||||
}
|
||||
|
||||
console.log('[DEBUG] Options received:', {
|
||||
hasChallenge: !!optionsData.options.challenge,
|
||||
rpId: optionsData.options.rp?.id,
|
||||
timeout: optionsData.options.timeout
|
||||
})
|
||||
|
||||
// Importiere @simplewebauthn/browser
|
||||
const mod = await import('@simplewebauthn/browser')
|
||||
|
||||
if (!mod.startRegistration) {
|
||||
throw new Error('startRegistration ist nicht verfügbar')
|
||||
}
|
||||
|
||||
status.value = 'waiting'
|
||||
|
||||
console.log('[DEBUG] Calling startRegistration on smartphone...')
|
||||
|
||||
// Rufe startRegistration auf
|
||||
const credential = await mod.startRegistration({ optionsJSON: optionsData.options })
|
||||
|
||||
console.log('[DEBUG] Credential received:', {
|
||||
id: credential.id,
|
||||
type: credential.type
|
||||
})
|
||||
|
||||
// Sende Credential-Response an den Server
|
||||
const verifyResponse = await fetch('/api/auth/register-passkey', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
registrationId: registrationId.value,
|
||||
credential
|
||||
})
|
||||
})
|
||||
|
||||
if (!verifyResponse.ok) {
|
||||
const errorData = await verifyResponse.json().catch(() => ({}))
|
||||
throw new Error(errorData.message || `Verification failed: ${verifyResponse.status}`)
|
||||
}
|
||||
|
||||
const verifyData = await verifyResponse.json()
|
||||
|
||||
if (verifyData.success) {
|
||||
status.value = 'success'
|
||||
console.log('[DEBUG] Registration successful!')
|
||||
} else {
|
||||
throw new Error(verifyData.message || 'Registrierung fehlgeschlagen')
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('[DEBUG] Registration error:', error)
|
||||
status.value = 'error'
|
||||
errorMessage.value = error.message || 'Unbekannter Fehler'
|
||||
}
|
||||
}
|
||||
|
||||
function retry() {
|
||||
status.value = 'loading'
|
||||
startRegistration()
|
||||
}
|
||||
</script>
|
||||
@@ -19,14 +19,16 @@ export default defineEventHandler((event) => {
|
||||
'/api/auth/passkeys/register',
|
||||
'/api/auth/passkeys/authentication-options',
|
||||
'/api/auth/passkeys/login',
|
||||
'/api/auth/passkeys/recovery'
|
||||
'/api/auth/passkeys/recovery',
|
||||
'/passkey-register-cross-device'
|
||||
]
|
||||
|
||||
const isPasskeyEndpoint = passkeyEndpoints.some(ep => path.startsWith(ep))
|
||||
// Logge auch alle Requests vom Smartphone (Mobile User-Agent)
|
||||
const isMobile = /Mobile|Android|iPhone|iPad/i.test(userAgent || '')
|
||||
const isPasskeyEndpoint = passkeyEndpoints.some(ep => path.startsWith(ep)) || (isMobile && path.startsWith('/'))
|
||||
|
||||
if (isPasskeyEndpoint) {
|
||||
const timestamp = new Date().toISOString()
|
||||
const isMobile = /Mobile|Android|iPhone|iPad/i.test(userAgent || '')
|
||||
|
||||
console.log('')
|
||||
console.log('─'.repeat(80))
|
||||
@@ -51,6 +53,12 @@ export default defineEventHandler((event) => {
|
||||
console.log(`[REQUEST] ⚠️ Wenn dieser Request vom Smartphone kommt, sollte der User-Agent Mobile/Android/iPhone enthalten`)
|
||||
}
|
||||
|
||||
// Logge alle Requests vom Smartphone (für Debugging)
|
||||
if (isMobile && path.startsWith('/') && !path.startsWith('/_nuxt') && !path.startsWith('/api')) {
|
||||
console.log(`[REQUEST] 📱 SMARTPHONE REQUEST - ${path}`)
|
||||
console.log(`[REQUEST] ⚠️ Wenn das Smartphone die Website öffnet, sollten hier Requests erscheinen`)
|
||||
}
|
||||
|
||||
console.log('─'.repeat(80))
|
||||
console.log('')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user