> For the complete documentation index, see [llms.txt](https://webauthn-doc.spomky-labs.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://webauthn-doc.spomky-labs.com/v5.4/pure-php/advanced-behaviours/attestation-and-metadata-statement.md).

# Attestation and Metadata Statement

{% hint style="danger" %}
**Important Notice:** The request for an Attestation Statement is reserved for applications necessitating a high degree of reliability, such as those operated by banking or financial institutions, government agencies, etc. Exercise caution and ensure your application's context requires such a level of trust before proceeding.
{% endhint %}

## Attestation Statement Support Manager

There are a few steps to achieve. First, you have to add support classes for all attestation statement types into your Attestation Metadata Manager.

{% hint style="warning" %}
For 4.5.0, the `TPMAttestationStatementSupport` class accepts a PSR-20 clock as argument. This argument will be mandatory for 5.0.0.

In the example below, we use `symfony/clock` component.
{% endhint %}

{% code lineNumbers="true" %}

```php
<?php

declare(strict_types=1);

use Cose\Algorithm\Manager;
use Cose\Algorithm\Signature\ECDSA;
use Cose\Algorithm\Signature\RSA;
use Webauthn\AttestationStatement\AndroidKeyAttestationStatementSupport;
use Webauthn\AttestationStatement\AttestationStatementSupportManager;
use Webauthn\AttestationStatement\FidoU2FAttestationStatementSupport;
use Webauthn\AttestationStatement\NoneAttestationStatementSupport;
use Webauthn\AttestationStatement\PackedAttestationStatementSupport;
use Webauthn\AttestationStatement\TPMAttestationStatementSupport;
use Webauthn\AttestationStatement\AppleAttestationStatementSupport;
use Symfony\Component\Clock\NativeClock;

//We need a PSR-20 clock
$clock = new NativeClock();

// You normally already do this
$attestationStatementSupportManager = AttestationStatementSupportManager::create();
$attestationStatementSupportManager->add(NoneAttestationStatementSupport::create());

// Additional classes to add
$attestationStatementSupportManager->add(FidoU2FAttestationStatementSupport::create());
$attestationStatementSupportManager->add(AppleAttestationStatementSupport::create());

$attestationStatementSupportManager->add(AndroidKeyAttestationStatementSupport::create());
$attestationStatementSupportManager->add(TPMAttestationStatementSupport::create($clock));

// Cose Algorithm Manager
// The list of algorithm depends on the algorithm list you defined in your options
// You should use at least ES256 and RS256 algorithms that are widely used.
$coseAlgorithmManager = Manager::create();
$coseAlgorithmManager->add(ECDSA\ES256::create());
$coseAlgorithmManager->add(RSA\RS256::create());

$attestationStatementSupportManager->add(PackedAttestationStatementSupport::create($coseAlgorithmManager));

// New in v5.3.0: Compound Attestation Statement Support
use Webauthn\AttestationStatement\CompoundAttestationStatementSupport;
$attestationStatementSupportManager->add(CompoundAttestationStatementSupport::create($attestationStatementSupportManager));
```

{% endcode %}

{% hint style="info" %}
**Compound Attestation Statement (v5.3.0+):** The Compound Attestation format allows multiple attestation statements to be bundled together. This is useful for authenticators that support multiple attestation mechanisms. The `CompoundAttestationStatementSupport` requires the `AttestationStatementSupportManager` to process the individual attestation statements within the compound format.
{% endhint %}

{% hint style="warning" %}
The Android SafetyNet Attestation API is deprecated. Full turndown is planned in June 2024. More information at <https://developer.android.com/training/safetynet/deprecation-timeline>

It is not described on this page, but available in the previous versions of the documentation.
{% endhint %}

## Metadata Statement Repository

Then, you must prepare a Metadata Statement Repository. This service will manage all Metadata Statements depending on their sources (local storage or distant service).

Your Metadata Statement Repository must implement the interface `Webauthn\MetadataService\MetadataStatementRepository` that has only one method:

* `findOneByAAGUID(string $aaguid)`: this method retrieves the `MetadataStatement` object with AAGUID. It shall return `null` in case of the absence of the MDS.

{% hint style="warning" %}
The library does not provide any Metadata Statement Repository. It is up to you to select the MDS suitable for your application and store them in your database.
{% endhint %}

## Status Report Repository

To prevent the use of rogue MDS or deprecated by the manufacturers, Status Reports may be used. The Status Report Repository is a simple service that implements the interface `Webauthn\MetadataService\StatusReportRepository` with a unique method:

* `findStatusReportsByAAGUID(string $aaguid)`: this method returns a list of Status Reports for the given AAGUID.

The verification's success or failure depends on the state reported in the most recent Status Report.

## Certificate Chain Validator

When an attestation statement is received, a certificate chain is constructed. This chain combines certificates from the Metadata Service (MDS), which are trusted, with those provided by the authenticator, which are untrusted.

The Certificate Chain Validator is responsible for this task. The library provides the class `Webauthn\MetadataService\CertificateChain\PhpCertificateChainValidator` that requires a Symfony Http Client ([for CRL verification](https://en.wikipedia.org/wiki/Certificate_revocation_list)) and a PSR-20 Clock.

{% code lineNumbers="true" %}

```php
<?php

use Webauthn\MetadataService\CertificateChain\PhpCertificateChainValidator;

$certificateChainValidator = PhpCertificateChainValidator::create(
    $httpClient,
    $clock
);
```

{% endcode %}

## Ceremony Step Manager Factory

The services described above must be set to the [Ceremony Step Manager Factory](/v5.4/pure-php/input-validation.md). The CSM you will create will verify the attestation statement sent by the authenticator.

{% code lineNumbers="true" %}

```php
<?php

declare(strict_types=1);

use Webauthn\CeremonyStep\CeremonyStepManagerFactory;

$csmFactory = new CeremonyStepManagerFactory();
$csmFactory->setAttestationStatementSupportManager($attestationStatementSupportManager);
$csmFactory->enableMetadataStatementSupport(
    $metadataStatementRepository,
    $statusReportRepository,
    $certificateChainValidator,
);
```

{% endcode %}

## Requesting Attestation Statement

By default, no Attestation Statement is asked to the Authenticators (type = `none`). To change this behavior, you just have to set the corresponding parameter in the `Webauthn\PublicKeyCredentialCreationOptions` object.

There are 3 conveyance modes available using PHP constants provided by the class `Webauthn\PublicKeyCredentialCreationOptions`:

* `ATTESTATION_CONVEYANCE_PREFERENCE_NONE`: the Relying Party is not interested in authenticator attestation (default)
* `ATTESTATION_CONVEYANCE_PREFERENCE_INDIRECT`: the Relying Party prefers an attestation conveyance yielding verifiable attestation statements, but allows the client to decide how to obtain such attestation statements.
* `ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT`: the Relying Party wants to receive the attestation statement as generated by the authenticator.

{% code lineNumbers="true" %}

```php
<?php

use Webauthn\PublicKeyCredentialCreationOptions;

$publicKeyCredentialCreationOptions = PublicKeyCredentialCreationOptions::create(
    $relyingParty,
    $userEntity,
    $challenge,
    attestation: PublicKeyCredentialCreationOptions::ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT,
);
```

{% endcode %}

### attestation on RequestOptions (v5.4.0+)

{% hint style="info" %}
**New in v5.4.0**
{% endhint %}

WebAuthn Level 3 §5.5 lets the relying party request an *assertion* attestation through the same `attestation` enum on `PublicKeyCredentialRequestOptions`. The accepted values are identical to creation options (`none`, `indirect`, `direct`, `enterprise`):

{% code lineNumbers="true" %}

```php
use Webauthn\PublicKeyCredentialRequestOptions;

$publicKeyCredentialRequestOptions = PublicKeyCredentialRequestOptions::create(
    challenge: random_bytes(32),
    rpId: 'example.com',
    attestation: PublicKeyCredentialRequestOptions::ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT,
);
```

{% endcode %}

### attestationFormats (v5.4.0+)

{% hint style="info" %}
**New in v5.4.0**
{% endhint %}

WebAuthn L3 §5.4 introduces `attestationFormats` — an ordered list of the formats the relying party prefers. It is exposed on both `PublicKeyCredentialCreationOptions` and `PublicKeyCredentialRequestOptions`:

{% code lineNumbers="true" %}

```php
use Webauthn\PublicKeyCredentialCreationOptions;

$publicKeyCredentialCreationOptions = PublicKeyCredentialCreationOptions::create(
    $relyingParty,
    $userEntity,
    $challenge,
    attestation: PublicKeyCredentialCreationOptions::ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT,
    attestationFormats: ['packed', 'tpm', 'fido-u2f'],
);
```

{% endcode %}

When the list is non-empty, `CheckAttestationFormatIsKnownAndValid` cross-checks the format the authenticator returned against it and throws `AuthenticatorResponseVerificationException` on mismatch. An empty list keeps the historical behaviour (any registered format is accepted). Empty lists are also omitted from the JSON payload, matching the spec's "absent == empty preference" semantics — no Stimulus change is needed: the field rides along inside `optionsJSON` and reaches `navigator.credentials.{create,get}()` as-is.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://webauthn-doc.spomky-labs.com/v5.4/pure-php/advanced-behaviours/attestation-and-metadata-statement.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
