Move passkey enrollment prompt to post-login dedicated page

After password login, users are routed through /Passkey/EnrollPrompt
before reaching the dashboard. The page shows an Enable / Maybe later
choice using the auth layout for a clean full-screen experience.
Users who already have a passkey are skipped past instantly.

Removes the floating bottom-right card from _Layout — the dedicated
page is a better UX touchpoint (one moment, right after login, rather
than a floating card on every page).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-25 16:41:01 -04:00
parent 92f71f62d0
commit edce8e8c4a
6 changed files with 144 additions and 84 deletions
@@ -895,33 +895,6 @@
<div id="tempdata-info-message" style="display:none;">@TempData["Info"]</div>
}
@* Passkey setup prompt — shown once per session to authenticated users who have no passkeys yet *@
@if (User.Identity?.IsAuthenticated == true && !User.IsInRole("SuperAdmin"))
{
<div id="passkey-setup-prompt" class="d-none"
style="position:fixed;bottom:1.25rem;right:1.25rem;z-index:1090;max-width:320px;">
<div class="card shadow-lg border-0">
<div class="card-body p-3">
<div class="d-flex align-items-start gap-2 mb-2">
<i class="bi bi-fingerprint text-primary" style="font-size:1.4rem;flex-shrink:0;margin-top:2px;"></i>
<div>
<div class="fw-semibold" style="font-size:.9rem;">Enable Face ID / Biometric Login</div>
<div class="text-muted" style="font-size:.8rem;">Skip the password next time — use your fingerprint or Face ID.</div>
</div>
<button type="button" id="passkey-dismiss-btn" class="btn-close ms-auto" style="font-size:.75rem;" aria-label="Dismiss"></button>
</div>
<p id="passkey-setup-status" class="small mb-2"></p>
<div class="d-flex gap-2">
<button id="passkey-enable-btn" type="button" class="btn btn-primary btn-sm flex-grow-1">
<i class="bi bi-fingerprint me-1"></i>Enable
</button>
<a href="/Passkey/Manage" class="btn btn-outline-secondary btn-sm">Manage</a>
</div>
</div>
</div>
</div>
}
@* Hidden container for ModelState errors (read by toast-notifications.js) *@
@if (!ViewData.ModelState.IsValid && ViewData.ModelState.ErrorCount > 0)
{