Files
harheimertc/test-cors.html
Torsten Schulz (local) 34968742f0
Some checks failed
Code Analysis (JS/Vue) / analyze (push) Failing after 55s
Add CORS testing documentation and HTML test page for Passkey Cross-Device Authentication
Introduce a comprehensive CORS testing guide in CORS_TEST_ANLEITUNG.md, detailing steps for testing OPTIONS and POST requests, along with expected responses. Additionally, add a new HTML test page (test-cors.html) to facilitate interactive testing of CORS headers and responses for the Passkey registration API. Update the server API to ensure proper CORS headers are set for Cross-Device Authentication, enhancing the overall testing and debugging process.
2026-01-08 11:14:22 +01:00

215 lines
7.1 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<title>CORS Test für Passkey Cross-Device</title>
<style>
body { font-family: monospace; padding: 20px; }
.test { margin: 20px 0; padding: 10px; border: 1px solid #ccc; }
.success { background: #d4edda; }
.error { background: #f8d7da; }
.info { background: #d1ecf1; }
button { padding: 10px 20px; margin: 5px; }
pre { background: #f5f5f5; padding: 10px; overflow-x: auto; }
</style>
</head>
<body>
<h1>CORS Test für Passkey Cross-Device Authentication</h1>
<div class="test info">
<h3>1. Origin-Info</h3>
<p><strong>Current Origin:</strong> <span id="currentOrigin"></span></p>
<p><strong>Is Secure Context:</strong> <span id="isSecure"></span></p>
</div>
<div class="test">
<h3>2. OPTIONS Preflight Test</h3>
<button onclick="testOptions()">Test OPTIONS Request</button>
<pre id="optionsResult"></pre>
</div>
<div class="test">
<h3>3. POST Request Test (mit Origin-Header)</h3>
<button onclick="testPost()">Test POST Request</button>
<pre id="postResult"></pre>
</div>
<div class="test">
<h3>4. Registration Options Test</h3>
<button onclick="testRegistrationOptions()">Test /api/auth/register-passkey-options</button>
<pre id="registrationResult"></pre>
</div>
<div class="test">
<h3>5. CORS Headers Check (Network Tab)</h3>
<p>Öffne die Browser-Entwicklertools (F12) → Network Tab</p>
<p>Führe die Tests oben aus und prüfe:</p>
<ul>
<li><strong>OPTIONS Request:</strong> Sollte Status 204 haben</li>
<li><strong>Response Headers:</strong> Sollten enthalten:
<ul>
<li>Access-Control-Allow-Origin: <span id="currentOrigin2"></span></li>
<li>Access-Control-Allow-Credentials: true</li>
<li>Access-Control-Allow-Methods: GET, POST, OPTIONS</li>
</ul>
</li>
</ul>
</div>
<script>
const origin = window.location.origin;
document.getElementById('currentOrigin').textContent = origin;
document.getElementById('currentOrigin2').textContent = origin;
document.getElementById('isSecure').textContent = window.isSecureContext ? 'JA ✓' : 'NEIN ✗';
async function testOptions() {
const resultEl = document.getElementById('optionsResult');
resultEl.textContent = 'Testing OPTIONS request...';
try {
const response = await fetch('/api/auth/register-passkey-options', {
method: 'OPTIONS',
headers: {
'Origin': origin,
'Access-Control-Request-Method': 'POST',
'Access-Control-Request-Headers': 'Content-Type'
}
});
const headers = {};
response.headers.forEach((value, key) => {
headers[key] = value;
});
resultEl.innerHTML = `
Status: ${response.status} ${response.status === 204 ? '✓' : '✗'}
Status Text: ${response.statusText}
Response Headers:
${JSON.stringify(headers, null, 2)}
CORS Headers Check:
- Access-Control-Allow-Origin: ${headers['access-control-allow-origin'] || 'FEHLT ✗'}
- Access-Control-Allow-Credentials: ${headers['access-control-allow-credentials'] || 'FEHLT ✗'}
- Access-Control-Allow-Methods: ${headers['access-control-allow-methods'] || 'FEHLT ✗'}
- Access-Control-Allow-Headers: ${headers['access-control-allow-headers'] || 'FEHLT ✗'}
`;
if (response.status === 204 && headers['access-control-allow-origin']) {
resultEl.parentElement.className = 'test success';
} else {
resultEl.parentElement.className = 'test error';
}
} catch (error) {
resultEl.textContent = `ERROR: ${error.message}\n${error.stack}`;
resultEl.parentElement.className = 'test error';
}
}
async function testPost() {
const resultEl = document.getElementById('postResult');
resultEl.textContent = 'Testing POST request...';
try {
const response = await fetch('/api/auth/register-passkey-options', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Origin': origin
},
body: JSON.stringify({
name: 'Test User',
email: 'test@example.com'
})
});
const headers = {};
response.headers.forEach((value, key) => {
headers[key] = value;
});
const data = await response.json().catch(() => ({ error: 'Could not parse JSON' }));
resultEl.innerHTML = `
Status: ${response.status}
Status Text: ${response.statusText}
Response Headers:
${JSON.stringify(headers, null, 2)}
Response Body:
${JSON.stringify(data, null, 2)}
CORS Headers Check:
- Access-Control-Allow-Origin: ${headers['access-control-allow-origin'] || 'FEHLT ✗'}
- Access-Control-Allow-Credentials: ${headers['access-control-allow-credentials'] || 'FEHLT ✗'}
`;
if (headers['access-control-allow-origin']) {
resultEl.parentElement.className = 'test success';
} else {
resultEl.parentElement.className = 'test error';
}
} catch (error) {
resultEl.textContent = `ERROR: ${error.message}\n${error.stack}`;
resultEl.parentElement.className = 'test error';
}
}
async function testRegistrationOptions() {
const resultEl = document.getElementById('registrationResult');
resultEl.textContent = 'Testing registration options endpoint...';
try {
const response = await fetch('/api/auth/register-passkey-options', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Test User',
email: 'test@example.com',
phone: ''
})
});
const headers = {};
response.headers.forEach((value, key) => {
headers[key] = value;
});
const data = await response.json();
resultEl.innerHTML = `
Status: ${response.status}
Status Text: ${response.statusText}
Response Headers (CORS):
- Access-Control-Allow-Origin: ${headers['access-control-allow-origin'] || 'FEHLT ✗'}
- Access-Control-Allow-Credentials: ${headers['access-control-allow-credentials'] || 'FEHLT ✗'}
- Access-Control-Allow-Methods: ${headers['access-control-allow-methods'] || 'FEHLT ✗'}
Response Body:
${JSON.stringify(data, null, 2)}
Options Structure:
- hasChallenge: ${data.options?.challenge ? 'JA ✓' : 'NEIN ✗'}
- hasRp: ${data.options?.rp ? 'JA ✓' : 'NEIN ✗'}
- hasUser: ${data.options?.user ? 'JA ✓' : 'NEIN ✗'}
- rpId: ${data.options?.rp?.id || 'FEHLT'}
- timeout: ${data.options?.timeout || 'FEHLT'}
`;
if (data.success && data.options && headers['access-control-allow-origin']) {
resultEl.parentElement.className = 'test success';
} else {
resultEl.parentElement.className = 'test error';
}
} catch (error) {
resultEl.textContent = `ERROR: ${error.message}\n${error.stack}`;
resultEl.parentElement.className = 'test error';
}
}
</script>
</body>
</html>