Files
suaveplan/packages/identity/auth/webauthn/src/parser/attestation-object.md
2026-05-27 23:47:53 +01:00

2.6 KiB

Attestation-object parser

Purpose

Decodes the CTAP 2.1 §6.5 attestation-object envelope returned by navigator.credentials.create(). The envelope is a top-level CBOR map with fmt (format identifier), authData (the opaque authenticator-data byte string the signature was made over), and attStmt (the format-specific attestation statement). The parser returns the parsed structure plus the already-decoded ParsedAuthData so per-format verifiers do not re-parse the authenticator data.

Features

  • Strict CBOR major-type checking — top level MUST be a map, fmt MUST be a text-string, authData MUST be a byte-string, attStmt MUST be a map.
  • Non-string attStmt keys reject with WEBAUTHN.MALFORMED_RESPONSE — only string-keyed maps are valid per CTAP 2.1.
  • Embedded authData is parsed via the universal authenticator-data parser; the per-format verifier consumes both the raw bytes (for signature verification) and the parsed structure (for flag inspection).
  • Zod schema validation on ParsedAttestationStmt so the public contract is stable.

Usage: Basic Example

import { parseAttestationObject } from "@suaveplan/webauthn/parser";

const env = parseAttestationObject(attestationObjectBytes);
console.log(env.fmt, env.parsedAuthData.flags.userVerified);

Usage: Advanced Example

import { parseAttestationObject } from "@suaveplan/webauthn/parser";

const env = parseAttestationObject(attestationObjectBytes);
switch (env.fmt) {
    case "packed":
        return verifyPacked(env, clientDataHash);
    case "tpm":
        return verifyTpm(env, clientDataHash);
    case "none":
        return verifyNone(env);
    default:
        throw new Error("unsupported attestation format");
}

API Reference

  • ParsedAttestationObject — { fmt: string, authData: Uint8Array, parsedAuthData: ParsedAuthData, attStmt: ParsedAttestationStmt }.
  • parseAttestationObject(bytes: Uint8Array): ParsedAttestationObject — full decode + structural validation; throws WEBAUTHN.MALFORMED_RESPONSE on every failure mode.

Implementation Notes

  • The authData byte string is kept raw on the returned envelope because every per-format verifier signs over the exact bytes the authenticator emitted — re-serialising via serializeAuthenticatorData would produce canonical bytes that may not match the authenticator's wire encoding.
  • decode from @suaveplan/cbor is used in strict mode (default) so trailing bytes after the top-level map are rejected. This is intentional — a well-formed attestation object has no padding.
  • The parser is universal; it imports zero DOM types and can be consumed server-side by relying-party verifiers.