Vincent
Created: October 29, 2023
Updated: April 30, 2025
Attestation can refer to three things (often in spoken language they are used interchangeable although they mean something different if taken precisely):
Firstly and more generally, attestation in the cryptographic space is a term where one party "attests" cryptographically to a statement to another party.
Secondly, during the registration phase in WebAuthn an attestation object is created by the authenticator and returned to the Relying Party. It is a container object which holds the following information:
fmt
)attStmt
- see below)authData
)The following process flow of the Registration shows the role of the attestation (object) in WebAuthn:
{ "root": { "id": "QFPlQVypLmmx71e0tmS3IfCFky0", "rawId": "QFPlQVypLmmx71e0tmS3IfCFky0", "response": { "attestationObject": { "fmt": "none", "attStmt": {}, "authData": { "rpIdHash": "t8DGRTBfls-BhOH2QC404lvdhe_t2_NkvM0nQWEEADc", "flags": { "userPresent": true, "userVerified": true, "backupEligible": true, "backupStatus": true, "attestedData": true, "extensionData": false }, "counter": 0, "aaguid": "00000000-0000-0000-0000-000000000000", "credentialID": "QFPlQVypLmmx71eOtmS3IfCFky0", "credentialPublicKey": "pQECAyYgASFYIEa-lpSiQ4P...", "parsedCredentialPublicKey": { "keyType": "EC2 (2)", "algorithm": "ES256 (-7)", "curve": 1, "x": "Rr6WlKJDg8MlbIq9mmHQzk2p2c_s7QoNKr7yMa7I8pM", "y": "tAELYp7h3sYNjZZIZgHPYiaSzF×QVT18cgZ_7wm13Vw" } } }, "clientDataJSON": { "type": "webauthn.create", "challenge": "AAABeB78HrIemh1jTdJICr_3QG_RMOhp", "origin": "https://passkeys.eu", "crossOrigin": false }, "transports": ["hybrid", "internal"], "publicKeyAlgorithm": -7 }, "authenticatorAttachment": "cross-platform" } }
In the screenshot above, no AAGUID and no attestation statement is provided.
Continue reading for a technical breakdown of the most important attributes.
In WebAuthn, attestation ensures that user authentication is secure and transparent. With the attestation statement, you can make sure that a credential was created on a specific authenticator / device.
These types of attestation refer to the attestation statement (not the attestation object). They are considered as a preference by the relying party (so the authenticator can behave differently as it's only a preference).
none
): For cases where privacy is of utmost concern or synced
devices are in play, this type provides no information about the device, ensuring the
user's privacy is intact. Another reason to use this value might be to save roundtrip to
a certificate authoriy (CA). none
is also the default value.indirect
): The relying party
prefers to get an attestation but allows the client to decide how to obtain attestation
statements. The client may replace the authenticator-generated attestation statements
with anonymous attestation statements to protect the user's privacy.direct
): This is the most transparent form. Here, the
relying party tells the authenticator that it wants an
attestation statement, so that the relying party gets
detailed information about the device, including its brand, model, and other specifics.
While it offers the highest transparency, it may raise privacy concerns in certain
scenarios or might not be really usable for synced credentials.enterprise
): The relying party
wants to receive an attestation statement that can include unique identifying
information. This type of attestation is typically used in businesses or organizations
that want to keep track of specific devices / authenticators.
Web browsers (user agents) should not provide this detailed attestation unless their
settings allow it specifically for the requesting party. If the settings do allow it,
the browser should tell the device when it's needed (at the start of the process) that
this specific type of attestation is being requested. The browser should then pass on
the device's unique ID and the attestation proof exactly as it receives them to the
relying arty.The attestation object contains many attributes, here's a quick explanation of some selected attributes:
"attestationObject": { "fmt": "none", "attStmt": {}, "authData": { "rpIdHash": "t8DGRTBfls-BhOH2QC404lvdhe_t2_NkvM0nQWEEADc", "flags": { "userPresent": true, "userVerified": true, "backupEligible": true, "backupStatus": true, "attestedData": true, "extensionData": false }, "counter": 0, "aaguid": "00000000-0000-0000-0000-000000000000", "credentialID": "QFPlQVypLmmx71eOtmS3IfCFky0", "credentialPublicKey": "pQECAyYgASFYIEa-lpSiQ4P...", "parsedCredentialPublicKey": { "keyType": "EC2 (2)", "algorithm": "ES256 (-7)", "curve": 1, "x": "Rr6WlKJDg8MlbIq9mmHQzk2p2c_s7QoNKr7yMa7I8pM", "y": "tAELYp7h3sYNjZZIZgHPYiaSzF×QVT18cgZ_7wm13Vw" } }
The attestationObject is a CBOR encoded object, containing information about the newly created credentials, the public key and other relevant data:
Contrary, to the attestation object above where attStmt
was left empty for readability
reasons, this is how a filled attestation statement would look like.
{ "alg": -65535, "sig": "MBHX7qov53SWqqPYCrxE5fcoAeDI83a0DzVJ2-N1KI6IAaCGGvINAIFzTEn44F6giANKte-8yEMDZbvbgDG1weaRj7SqsVaTty-TEQ", "ver": "2.0", "x5c": [ "MIIFwDCCA6oIaK6tZ7M", "MIIG6zCCBNpG18-MCJrHyrpMT-ul7RgxE4dFxqcG59ftTXqJ1f-X_Lpo7K-d7OgKoQrUgzxgATz8YXtFAk3rE1cHXvW9W52V637eAihKn9-UKC0ijzVXrBGX4Iq1o1M0ZfR-tFoOn498xasMCTnharKiM562GBLVJtlvV3DMSLEBl5SfuGM-qYjQgTQknXccks9guCmNaN_b2fo1DisbufXfjM3DVaMqx7IJpSc3wAnxooMrAYGpPM" ], "pubArea": "AAEACwAw_c3Ousz865mUPx8O3w", "certInfo": "_1RDR4AXAniCekfsiDI" }
alg
: The alg property indicates the cryptographic algorithm identifier used by the
authenticator for signing the attestation statement.sig
: The sig property contains the digital signature generated by the authenticator.
This signature is used to verify the authenticity of the attestation statement.ver
: The ver property specifies the version of the attestation statement format.x5c
: The x5c array contains one or more X.509 certificates that form a certification
path, which assists in validating the attestation.pubArea
: The pubArea property contains detailed information about the public key and
the authenticator's characteristics.certInfo
: The certInfo property typically includes information about the certification
of the authenticator by a trusted party."clientDataJSON": { "type": "webauthn.create", "challenge": "AAABeB78HrIemh1jTdJICr_3QG_RMOhp", "origin": "https://www.passkeys-debugger.io", "crossOrigin": false }
Read more about clientDataJSON
in the
respective glossary article.
"transports": [ "hybrid", "internal" ]
The transports-property indicates mechanisms through which an authenticator can communicate with a client. Some common, sample value combinations are:
"transports": ["internal","hybrid"]
: Passkeys can be used from the
platform authenticator (e.g. Face ID, Touch ID,
Windows Hello) or via cross-device authentication (using
QR code & Bluetooth)."transports": ["internal"]
: Passkeys can be used from the
platform authenticator (e.g. Face ID, Touch ID,
Windows Hello)transports
property set: default behavior which gives no indications.Attestation (the attestation statement) in WebAuthn is important as it offers proof of the genuineness of an authenticator. It ensures that the authentication process is carried out by a trusted device, thereby safeguarding against potential security threats.
Ben Gould
Head of Engineering
I’ve built hundreds of integrations in my time, including quite a few with identity providers and I’ve never been so impressed with a developer experience as I have been with Corbado.
3,000+ devs trust Corbado & make the Internet safer with passkeys. Got questions? We’ve written 150+ blog posts on passkeys.
Join Passkeys CommunityYes, as passkeys can be synced across devices (e.g. from iPhone to MacBook
via Keychain), relying parties cannot really
determine anymore which attested device is really logging into an app or website.
Therefore, Apple and Google decided that for synced passkeys, they will not provide
attestation statements anymore. However, to improve the UX for relying parties and give
them the opportunity to recognize and display passkeys from the Apple and Google ecosystem
(iCloud Keychain and
Google Password Manager), the
AAGUID will be still provided (as long as attestation is set to
direct
or indirect
in the WebAuthn server settings for the
PublicKeyCredentialCreationOptions
. See this
GitHub issue for details.
If you want to integrate passkey authentication in
your website and app, and want to offer your users a great passkey UX, you should consider
the following. We assume you build your solution primarily for a scenario where most of
your users use a Windows, iOS, macOS or
Android operating system. Moreover, we assume that
most of the passkeys (apart from Windows) are synced passkeys. As neither iOS, macOS nor
Android send an attestation statement anymore, the
real validation of an authenticator is no longer used (for Windows this still works,
probably as Windows does not offer synced passkeys via
Windows Hello yet). However, to get the
AAGUID, e.g. for better passkey management in the account settings, we
recommend to set the attestation preference to indirect
, as this would still allow to
get the AAGUID while the attestation statement is either sent
(Windows) or not sent (iOS, macOS, Android).
The FIDO metadata service provides a repository of metadata for various authenticator. During attestation, this service can be queried to fetch and validate details about the authenticator, ensuring accuracy and enhancing the trustworthiness of the process. The FIDO metadata service checks the attestation statement (not the attestation object).
Yes, direct attestation (in the attestation statement), while offering the highest transparency by providing detailed information about the device, can raise privacy concerns in certain scenarios. It's crucial to assess the need for transparency versus privacy when choosing the type of attestation.
WebAuthn offers different types of attestations
preferences – none, indirect, direct and enterprise. For scenarios where
user privacy is
important, attestation=none
can be employed, which provides no details about the device,
ensuring the user's privacy remains protected.
Table of Contents
Enjoyed this read?
🤝 Join our Passkeys Community
Share passkeys implementation tips and get support to free the world from passwords.
🚀 Subscribe to Substack
Get the latest news, strategies, and insights about passkeys sent straight to your inbox.