2.6 KiB
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,
fmtMUST be a text-string,authDataMUST be a byte-string,attStmtMUST be a map. - Non-string
attStmtkeys reject withWEBAUTHN.MALFORMED_RESPONSE— only string-keyed maps are valid per CTAP 2.1. - Embedded
authDatais 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
ParsedAttestationStmtso 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; throwsWEBAUTHN.MALFORMED_RESPONSEon every failure mode.
Implementation Notes
- The
authDatabyte string is kept raw on the returned envelope because every per-format verifier signs over the exact bytes the authenticator emitted — re-serialising viaserializeAuthenticatorDatawould produce canonical bytes that may not match the authenticator's wire encoding. decodefrom@suaveplan/cboris 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.