Skip to content

WebAuthn and FIDO2

A WebAuthn registration hands the server an attestation object: CBOR, and the reason this library exists. It is a map of three entries — the attestation format, the statement itself, and the authenticator data as raw bytes:

use CBOR\Decoder;
use CBOR\MapObject;
use CBOR\StringStream;

$decoder = Decoder::create();

$attestationObject = $decoder->decode(StringStream::create($binaryData));

if (! $attestationObject instanceof MapObject) {
    throw new RuntimeException('An attestation object is a CBOR map');
}

$format = $attestationObject->get('fmt')->normalize();       // "packed", "none", "tpm"…
$statement = $attestationObject->get('attStmt');             // a map, whose shape depends on the format
$authenticatorData = $attestationObject->get('authData')->getValue(); // bytes, left as they are

Keep authData as the byte string it is. It is signed, so a single byte re-encoded differently breaks the signature; parse it as the binary structure WebAuthn specifies — flags, counter, credential — not as CBOR.

The credential public key, on the other hand, sits inside authData and is CBOR: a COSE key, a map whose keys are negative and positive integers rather than strings.

// $credentialPublicKey are the bytes that follow the credential id in authData
$key = $decoder->decode(StringStream::create($credentialPublicKey));

$kty = $key->get(1)->normalize();  // key type
$alg = $key->get(3)->normalize();  // algorithm

Do not write a WebAuthn server by hand

web-auth/webauthn-framework does all of the above, with the attestation statement formats, the verification of the signature and the checks the specification asks for. It uses this library underneath. The code here is for reading what is on the wire, or for debugging what a client sent.