Implementation path
- Choose password sign-in or call the public passkey capability endpoint for the device-based flow.
- Start enrollment or sign-in from the browser with credentials: include when using the session cookie.
- For passkeys, pass server-issued WebAuthn options to the browser ceremony and send the result to the matching complete endpoint; for passwords, submit the password only to the matching server endpoint.
- Handle the server response as authoritative; only a successful password proof or verified passkey completion establishes a session.
- Keep recovery separate: recovery proof leads to replacement-passkey completion, not direct session issuance.
Browser boundary
const response = await fetch("/api/auth/signin/passkey/options", {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json", Origin: window.location.origin },
body: JSON.stringify({ email: "person@example.com" })
});
const options = await response.json();
// Pass options to the reviewed WebAuthn browser library.
// Send its assertion only to /api/auth/signin/passkey/complete.