feat: Passwordless cross-device authentication

- Arkitektur: docs/auth/passwordless-architecture.md
- Backend: iom/quixzoom-auth-service/ (FastAPI + Redis)
- Webb: quixzoom-market-pages/se/login/ (QR-kod + polling)
- App: iom/quixzoom-app/src/features/auth/ (push + deep links)

Flöde: QR-kod → app-godkännande → webb-inloggad
This commit is contained in:
Bernt
2026-07-07 07:11:50 +00:00
parent 4aa984ad74
commit 6989a98d75
61843 changed files with 5491611 additions and 872231 deletions
+5 -5
View File
@@ -8,21 +8,21 @@
align-items: center; justify-content: center; min-height: 100vh; margin: 0; }
.box { text-align: center; }
.spinner { width: 40px; height: 40px; border: 3px solid #1e293b;
border-top: 3px solid #6366f1; border-radius: 50%; animation: spin 0.8s linear infinite;
border-top: 3px solid #6366f1; border-radius: var(--radius-full); animation: spin 0.8s linear infinite;
margin: 0 auto 16px; }
@keyframes spin { to { transform: rotate(360deg); } }
h2 { margin: 0 0 8px; font-size: 1.2rem; }
p { color: #64748b; font-size: 0.85rem; margin: 0; }
#creds { background: #1e293b; border-radius: 10px; padding: 16px; margin-top: 20px;
#creds { background: #1e293b; border-radius: var(--radius-md); padding: 16px; margin-top: 20px;
text-align: left; min-width: 280px; display: none; }
.row { display: flex; justify-content: space-between; align-items: center;
margin-bottom: 10px; gap: 12px; }
label { color: #94a3b8; font-size: 0.8rem; min-width: 80px; }
code { color: #fbbf24; font-size: 0.85rem; flex: 1; }
.copy-btn { background: #6366f1; color: #fff; border: none; border-radius: 4px;
.copy-btn { background: #6366f1; color: #fff; border: none; border-radius: var(--radius-sm);
padding: 3px 10px; cursor: pointer; font-size: 0.75rem; white-space: nowrap; }
.open-btn { display: inline-flex; align-items: center; gap: 8px; background: #6366f1;
color: #fff; text-decoration: none; padding: 10px 24px; border-radius: 8px;
color: #fff; text-decoration: none; padding: 10px 24px; border-radius: var(--radius-md);
font-weight: 700; font-size: 0.9rem; margin-top: 16px; }
</style>
</head>
@@ -61,7 +61,7 @@ function copy(id, btn) {
const text = document.getElementById(id).textContent;
navigator.clipboard.writeText(text).then(() => {
const orig = btn.textContent;
btn.textContent = '';
btn.textContent = '<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3 8L6.5 11.5L13 4.5" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
setTimeout(() => btn.textContent = orig, 1500);
});
}