src/lib/passkey-ceremony.ts
Rama main · réplica de lectura del repositorio original.
// Reading a failed WebAuthn ceremony, for the two hooks that run one.
//
// Sign-in and registration fail in the same two harmless ways - the diver closed
// the sheet, or the ceremony was stood down - and telling those apart from a real
// failure is subtle enough that both hooks reading the same function is the point
// of this module.
import { WebAuthnError } from "@simplewebauthn/browser";
/**
* Whether an error means the diver backed out rather than anything failing.
*
* Two shapes, one meaning. `ERROR_CEREMONY_ABORTED` is what v13 raises when a
* ceremony is cancelled by an abort signal - which is how the sign-in hook stands
* its conditional ceremony down, and how v13 itself stands one down when another
* ceremony starts. Matched on `code`, which is the documented contract; v13 also
* copies the wrapped `DOMException`'s `name` onto the wrapper, so `"AbortError"`
* happens to work too, but that is incidental and unwritten-down.
*
* `NotAllowedError` is the sheet being dismissed, and reaches us through v13's
* deliberate passthrough - one code (`ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY`) for
* every spec error it declines to reinterpret, so the copied `name` is what
* distinguishes it. The spec overloads that error on purpose - dismissed, timed
* out, and "no credential matched" are one error, so that a page cannot ask
* whether an account has a passkey - and every reading of it is a diver who chose
* to stop. Reporting it would scold someone for closing a dialog.
*/
export function isCeremonyDismissed(error: unknown): boolean {
if (!(error instanceof WebAuthnError)) return false;
return (
error.code === "ERROR_CEREMONY_ABORTED" || error.name === "NotAllowedError"
);
}