Files
2026-05-27 23:29:53 +01:00

4.5 KiB

Capability Spec Delta: webauthn (webauthn)

Package: @suaveplan/webauthn Status: PROPOSED (companion delta of add-webauthn-mds3)

Every requirement below carries a **Verified by:** line at authoring time. No exceptions.

MODIFIED Requirements

Requirement: Attestation verification dispatch

The package SHALL export verifyAttestation(input: VerifyAttestationInput): Promise<AttestationVerifyResult> from the ./verifier subpath. The function SHALL dispatch on input.attestationObject.fmt to the per-format verifier registered in input.registry, throwing WEBAUTHN.ATTESTATION_FORMAT_UNSUPPORTED when no verifier is registered. VerifyAttestationInput SHALL accept an optional metadata?: MetadataResolver field (typed via import type from @suaveplan/webauthn-mds3 — runtime-optional) and an optional revokedStatuses?: ReadonlySet<AuthenticatorStatus> field. AttestationVerifyResult SHALL carry an optional metadata?: MetadataLookup field. When input.metadata is undefined the returned AttestationVerifyResult SHALL be byte-identical to the pre-modification contract (strict back-compat). When input.metadata is supplied, after the per-format verifier returns, verifyAttestation SHALL resolve the AAGUID — or, for fmt === "fido-u2f" or an all-zero AAGUID, the SHA-1 SKI of the leaf attestation certificate (FIDO MDS3 §3.1.6) — call resolveByAaguid / resolveByAttestationCertificateKeyId on the supplied resolver, set result.metadata to the returned MetadataLookup (or omit when undefined), and downgrade result.trusted to false when the lookup's currentStatus is in revokedStatuses ?? DEFAULT_REVOCATION_STATUSES.

Scenario: dispatches to registered format verifier

  • WHEN verifyAttestation({ attestationObject: { fmt: "packed", ... }, registry: defaultAttestationRegistry(), ... }) is called
  • THEN the result is produced by the packed verifier and includes trustPath, attestationType, trusted

Scenario: throws WEBAUTHN.ATTESTATION_FORMAT_UNSUPPORTED on unknown fmt

  • WHEN verifyAttestation({ attestationObject: { fmt: "unknown-fmt", ... }, registry: emptyRegistry }) is called
  • THEN the call rejects with WEBAUTHN.ATTESTATION_FORMAT_UNSUPPORTED

Scenario: omits metadata field when no resolver injected (back-compat)

  • WHEN verifyAttestation(input) is called with input.metadata === undefined
  • THEN the resolved AttestationVerifyResult has metadata === undefined and is byte-for-byte identical to the legacy (pre-modification) result for the same inputs

Scenario: augments result with metadata when resolver injected

  • GIVEN a MetadataResolver whose resolveByAaguid returns a MetadataLookup with currentStatus === "FIDO_CERTIFIED_L1"
  • WHEN verifyAttestation({ ..., metadata: resolver }) is called against a packed attestation carrying a known AAGUID
  • THEN result.metadata deep-equals the lookup and result.trusted is the verifier's original value (unchanged)

Scenario: downgrades trusted=false when currentStatus is revoked

  • GIVEN a MetadataResolver whose resolveByAaguid returns a MetadataLookup with currentStatus === "REVOKED"
  • WHEN verifyAttestation({ ..., metadata: resolver }) is called and the per-format verifier returned trusted: true
  • THEN the merged result.trusted is false and result.metadata.currentStatus === "REVOKED"

Scenario: resolves U2F by attestation-cert SKI

  • GIVEN a MetadataResolver and a fido-u2f attestation whose leaf cert has SKI 0xDEAD…
  • WHEN verifyAttestation({ ..., metadata: resolver }) is called
  • THEN the resolver's resolveByAttestationCertificateKeyId(0xDEAD…) is invoked exactly once and resolveByAaguid is never called

Verified by: packages/auth/webauthn/src/verifier/verify-attestation.test.ts::"dispatches to registered format verifier" AND packages/auth/webauthn/src/verifier/verify-attestation.test.ts::"throws WEBAUTHN.ATTESTATION_FORMAT_UNSUPPORTED on unknown fmt" AND packages/auth/webauthn/src/verifier/verify-attestation.test.ts::"omits metadata field when no resolver injected (back-compat)" AND packages/auth/webauthn/src/verifier/verify-attestation.test.ts::"augments result with metadata when resolver injected" AND packages/auth/webauthn/src/verifier/verify-attestation.test.ts::"downgrades trusted=false when currentStatus is revoked" AND packages/auth/webauthn/src/verifier/verify-attestation.test.ts::"resolves U2F by attestation-cert SKI"