Authenticator Metadata and MDS3
The FIDO Alliance Metadata Service is the directory that turns an AAGUID into facts: which authenticator model produced a credential, what it has been certified to do, and whether anything has since gone wrong with it. This page covers what the service publishes, how to verify and cache the metadata blob safely, and — most importantly — how to build a policy on top of it that does not break when a device is missing from the directory. It sits under WebAuthn & FIDO2 Protocol Fundamentals, and it only becomes relevant once you have decided to collect attestation at all, a decision covered in the attestation conveyance policy guide.
Concept Definition and Spec Grounding
An authenticator model is identified by its AAGUID: sixteen bytes that appear in the attested credential data of a registration response, and only there. Every unit of a given model shares the same value, which is precisely what makes it usable — it identifies a product rather than a person. Synced platform passkeys typically report an all-zero AAGUID, because there is no single device model to name.
The Metadata Service publishes a signed document, commonly called the metadata blob, containing one entry per certified model. Each entry carries the vendor and model description, the FIDO certification level achieved, the supported cryptographic algorithms, the available user-verification methods, and a list of status reports recording certification changes over time — including revocations issued after a disclosed vulnerability.
Two properties of the service matter more than its contents. First, it is signed: the blob is a token whose signature chains to a FIDO Alliance root, and an unverified blob is an untrusted input regardless of where it came from. Second, it is incomplete by design. Certification is voluntary and lags new hardware, so a substantial share of perfectly legitimate authenticators — including most platform authenticators — have no entry at all.
Architecture and Data Flow
Metadata is a background dependency, not a request-path one. The correct shape is a scheduled job that fetches the blob, verifies it, and writes the parsed entries into a local store; the registration endpoint then performs an in-memory or single-read lookup against that store and never touches the network.
Building it the other way round — fetching metadata during a ceremony — creates a hard dependency on an external service inside your sign-in flow. When that service is slow or unreachable, registrations fail for reasons entirely unrelated to the user, the authenticator or your own code.
The store needs three things beyond the entries themselves: the blob number, so you can tell whether an update actually advanced; the nextUpdate date, so you can alert when the cache goes stale; and the timestamp of the last successful verification, so an operator can answer “how old is this data” without reading logs.
Implementation Guide
Step 1 — fetch on a schedule, not on demand. Daily is generous; the blob changes infrequently and the cost of being a day behind is negligible compared with the cost of a network dependency in your registration path.
Step 2 — verify the signature before parsing anything. The blob is a signed token. Verify it against the FIDO Alliance root you have pinned, validate the certificate chain, and check any revocation information the chain provides. Treat a verification failure as “keep the previous blob” rather than “accept the new one anyway”.
Step 3 — refuse to go backwards. The blob carries a sequence number. A fetch that returns an older number than the one you hold is either a mistake or a rollback attack, and it must not replace your cached copy.
Step 4 — index by AAGUID and store the whole entry. Storing only the fields you currently use guarantees a re-fetch the first time a policy changes. The entries are small; keep them.
Step 5 — expose the cache age as a metric. Alert on the age rather than on the job’s exit status, because a job that succeeds while writing nothing is the failure mode you will actually encounter.
Step 6 — look up with an explicit unknown case. Every lookup has three outcomes: a known entry, an all-zero AAGUID indicating no model identity, and a genuine miss. Handle all three at the call site rather than allowing a null to propagate.
Validation Checklist
Error Reference Table
| Condition | What it means | What to do |
|---|---|---|
| Blob signature invalid | The document is not from the Metadata Service, or the chain is broken | Keep the cached blob, alert, do not fail registrations |
| Blob number not advancing | The endpoint is serving a cached or rolled-back copy | Alert on cache age; investigate the fetch path |
nextUpdate in the past |
Your sync has been failing silently | Alert; decide in advance whether stale data is still usable |
| AAGUID all zeros | The authenticator reports no model identity | Normal for synced passkeys — do not treat as an error |
| AAGUID not in the blob | Uncertified, new, or simply absent | Apply your documented unknown-model policy |
| Status report shows a revocation | The model’s certification was withdrawn | Flag affected credentials; decide whether to force re-enrolment |
Platform and Library Notes
Server libraries differ substantially in how much of this they do for you. Some ship a metadata client that handles fetching, verification and caching; others expose only a parser and leave the trust decisions to you. The distinction that matters is whether the library verifies the blob signature — if it does not, and you did not, then the entries you are consuming are attacker-influenceable.
Platform authenticators are the common source of surprise. A synced passkey generally reports an all-zero AAGUID, so metadata lookups are simply not applicable, and code that treats “no metadata entry” as a policy failure will reject the majority of consumer registrations. Some managed platform authenticators do report a real AAGUID, which is why the all-zero case and the unknown case must be distinguished rather than collapsed.
Hardware security keys are where the service earns its place. They report stable AAGUIDs, they are certified, and their entries carry the certification level that an enterprise policy is usually written against.
Pitfalls and Security Hardening
1. Trusting an unverified blob. The entire value of the service rests on its signature. A blob fetched over TLS but not verified is an input controlled by anything that can influence your egress path.
2. Fetching during a ceremony. This converts an external service’s availability into your registration availability, and it is invisible until the service has an incident.
3. Treating an absent entry as a failure. Certification is voluntary and lags hardware releases. A policy of rejecting the unknown is defensible inside a managed enterprise and unworkable on the open web.
4. Reading the AAGUID without verifying attestation. The value arrives in a client-supplied payload. Only a verified attestation statement makes it a claim by the manufacturer rather than a claim by the sender.
5. Never re-evaluating. Status reports change. A model that was certified when a credential was enrolled may have been revoked since, and a policy evaluated only at registration will not notice.
6. Merging policy and verification errors. “The chain did not validate” and “this model is not on our allow-list” are different events with different responses, and a single error code makes both unreadable.
Frequently Asked Questions
Do I need metadata if I do not collect attestation?
No. Without a verified attestation statement there is no trustworthy AAGUID to look up, and the metadata service has nothing to contribute. Metadata is the second half of an attestation policy, never a standalone feature.
What proportion of registrations will have a usable entry?
In a consumer product, a small minority — most enrolments are synced platform passkeys reporting no model identity. In an enterprise deployment issuing certified hardware keys, close to all of them. The difference is large enough that a policy written for one population is usually wrong for the other.
Should a revoked model’s credentials be deleted?
Flag them first. Immediate revocation on a status change turns a vendor announcement into a mass lockout, and the appropriate response depends on what the report actually says — a certification lapse is not the same as a key-extraction vulnerability. Flagging gives you the option to require re-enrolment at the next sign-in instead.
How large is the blob?
Small enough to hold in memory comfortably, and it grows slowly. There is no reason to store only a subset of fields or to fetch entries individually.
Can I use a third-party mirror of the metadata?
Only if you still verify the signature against the FIDO Alliance root, in which case the mirror is just a transport and its trustworthiness does not matter. Consuming a mirror’s parsed output without verification means trusting the mirror with your enrolment policy.
Does the AAGUID identify a device uniquely?
No — it identifies a model, and that is deliberate. Thousands or millions of units share one value, which is what makes it safe to disclose. Unit-level identity exists only through enterprise attestation, which platforms gate behind managed-device policy.
Writing an Authenticator Policy That Survives Contact
A metadata-backed policy is only as good as its treatment of the cases the directory does not cover, and those cases are the majority in most deployments. Three decisions determine whether the policy is usable.
The unknown-model decision. When a verified attestation carries an AAGUID with no metadata entry, you either accept the registration without a model claim or refuse it. Refusing is correct in an enterprise that issues its own hardware and can enumerate every model it supports. It is wrong almost everywhere else, because new devices reach users before certification reaches the directory, and because a policy that refuses the unknown will refuse a device your own procurement team bought last month.
The no-attestation decision. A registration carrying no attestation statement at all is not a metadata problem, but it lands in the same code path and needs an answer. In a consumer product the answer is to accept it: the credential is perfectly valid, it simply carries no device claim. In a regulated deployment the answer may be to refuse, in which case the user needs an interface that explains what kind of authenticator they must use.
The tier decision. Between accept and refuse there is a middle option that is usually the right one: accept the credential, record that it carries no verified model claim, and let that fact gate the higher-assurance surfaces rather than sign-in itself. A user with an unrecognised authenticator can still read their account; they simply cannot approve a transfer without a second, recognised credential. This keeps enrolment open while giving the policy somewhere real to bite.
Write all three decisions down next to the code that implements them, because their rationale is exactly what a future reader will lack — and because the most common way an attestation policy fails is that somebody disables a check to stop the errors, having no way to tell which of the three cases the errors represented.
Keeping the Dependency Honest
Metadata is an external dependency with an unusual failure mode: it degrades silently, and the degradation only becomes visible when a policy decision is wrong rather than when the fetch fails.
Monitor three things. The age of the cached blob, which should never exceed the publication interval by more than a small margin. The number of entries, which should grow slowly and never shrink — a sudden drop means a partial parse or a truncated fetch that verification did not catch. And the rate of unknown-AAGUID lookups, which is your early warning that the cache has stopped updating: a directory frozen in time produces steadily more unknowns as users buy newer hardware.
Test the verification path, not just the parse. A fixture containing a correctly signed blob and a fixture containing one with a broken signature, both run through your loader, prove that the check is actually wired in. This sounds trivial and is the single most commonly missing test in metadata code, because the happy path works identically whether or not verification runs.
Finally, decide in advance what happens when the cache is stale beyond your tolerance. Continuing with old data is usually right — the entries are still true, they are simply incomplete — but it should be a documented choice with an alert attached rather than an accident of how the code was written.
One last note on scope: nothing in this page changes how a sign-in is verified. Metadata shapes who may enrol and what an enrolled credential is trusted to authorise, and it does so once, at registration. Every subsequent assertion is validated by the signature over the challenge exactly as it would be in a deployment that never touched the Metadata Service at all, which is worth stating plainly whenever the topic reaches a security review.
Related
- WebAuthn & FIDO2 Protocol Fundamentals — the parent topic area and the protocol trust model
- Attestation vs Assertion Explained — where the AAGUID comes from and why attestation must be verified first
- Verifying the FIDO Metadata Blob — the signature and chain checks in detail
- Looking Up Authenticators by AAGUID — the lookup path and the three outcomes it must handle
- Attestation Conveyance Policy Selection Guide — deciding whether to request attestation at all