passkey-utils.ts

1.3 KB · raw

1/**2 * passkey-utils.ts — WebAuthn relying-party-id validation.3 *4 * The native browser enforces that a page may only request a passkey whose5 * rpId is a registrable-domain-suffix of the page's own origin. On Firefox,6 * Peach intercepts `navigator.credentials` in a MAIN-world content script and7 * services the ceremony itself, so Peach — not the browser — must re-impose8 * that rule. Without it a page at `evil.com` could request (and Peach would9 * happily mint) a credential scoped to `google.com` (SEV-1-A).10 */1112import { parse } from "tldts";1314/**15 * Validates that `rpId` is equal to, or a registrable-domain-suffix of, the16 * hostname of `callerOrigin`. Mirrors WebAuthn §7.1 step 6 / §7.2 step 8.17 * Private suffixes are enabled because services such as github.io host18 * unrelated tenants beneath the same public suffix.19 */20export function isValidRpId(rpId: string, callerOrigin: string): boolean {21  let callerHost: string;22  try {23    callerHost = new URL(callerOrigin).hostname;24  } catch {25    return false;26  }27  if (!rpId || !callerHost) return false;2829  const id = rpId.toLowerCase();30  const host = callerHost.toLowerCase();31  if (!id.includes(".")) return false;3233  const rp = parse(id, { allowPrivateDomains: true });34  const caller = parse(host, { allowPrivateDomains: true });35  return rp.domain === id && caller.domain === rp.domain;36}