P02 Lab 12 — WebAuthn / Passkey Ceremony Verifier

WARMUP: Chapters 4–8 (TLS/identity); the phishing-resistant-MFA thread.

Why this matters

The whole track keeps recommending phishing-resistant MFA (WebAuthn/passkeys) over push/SMS. Its resistance comes from the relying-party's server-side checks on the registration (create) and authentication (get) ceremonies — above all origin binding: the authenticator signs over the origin, so an assertion proven to the real site cannot be replayed to a look-alike phishing site. This lab implements those checks (not the COSE/CBOR crypto): challenge freshness, origin + rp_id match, ceremony type, user presence/verification, signature validity, and signature-counter clone detection.

What you build (lab.py)

  • verify_registration(ceremony, require_uv) — challenge → origin → rp_id → type (webauthn.create) → user present → user verified.
  • verify_authentication(ceremony, require_uv) — the same common checks (webauthn.get), then signature validity, then clone detection (a non-increasing signature counter ⇒ cloned-authenticator, with the all-zero counter case allowed).

Cases the tests cover

  • Valid create/get ceremonies; challenge mismatch (replay), origin mismatch (the phishing defense), rp_id mismatch, type mismatch; user-not-present / user-not-verified (with require_uv toggle); bad signature; counter regression/equality ⇒ clone; all-zero counters allowed.

Run

pip install -r requirements.txt
LAB_MODULE=solution pytest -q
pytest -q

Hardening / extensions

  • Verify the real attestation statement (packed/TPM/Apple) and the COSE public key/signature.
  • Enforce allowed algorithms and an AAGUID allowlist; bind to a user handle.
  • Add backup-eligibility/backup-state (passkey sync) policy and per-RP credential scoping.

Interview / resume

"Built a WebAuthn relying-party ceremony verifier — challenge, origin binding, rp_id, user presence/verification, signature, and signature-counter clone detection — demonstrating exactly why WebAuthn is phishing-resistant: the assertion is bound to the origin and can't be replayed to a look-alike site."

Limitations: models the protocol checks, not the COSE/CBOR attestation/assertion cryptography (left as an extension); signature_valid is supplied.