Skip to content

Commit 9aa1a6a

Browse files
committed
chore: simplify metadata statement check
1 parent 4d7c777 commit 9aa1a6a

File tree

1 file changed

+40
-36
lines changed

1 file changed

+40
-36
lines changed

src/webauthn/src/CeremonyStep/CheckMetadataStatement.php

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -79,41 +79,49 @@ public function process(
7979
$attestedCredentialData !== null || throw AuthenticatorResponseVerificationException::create(
8080
'No attested credential data found'
8181
);
82-
$aaguid = $attestedCredentialData->aaguid
83-
->__toString();
84-
if ($publicKeyCredentialOptions->attestation === null || $publicKeyCredentialOptions->attestation === PublicKeyCredentialCreationOptions::ATTESTATION_CONVEYANCE_PREFERENCE_NONE) {
85-
$this->logger->debug('No attestation is asked.');
86-
if ($aaguid === '00000000-0000-0000-0000-000000000000' && in_array(
87-
$attestationStatement->type,
88-
[AttestationStatement::TYPE_NONE, AttestationStatement::TYPE_SELF],
89-
true
90-
)) {
91-
$this->logger->debug('The Attestation Statement is anonymous.');
92-
$this->checkCertificateChain($attestationStatement, null);
93-
return;
94-
}
82+
83+
/**
84+
* RP does not want to verify the authentication attestation.
85+
* @see https://www.w3.org/TR/webauthn-3/#dom-attestationconveyancepreference-none
86+
*/
87+
if (in_array(
88+
$publicKeyCredentialOptions->attestation,
89+
[null, PublicKeyCredentialCreationOptions::ATTESTATION_CONVEYANCE_PREFERENCE_NONE],
90+
true
91+
)) {
9592
return;
9693
}
97-
// If no Attestation Statement has been returned or if null AAGUID (=00000000-0000-0000-0000-000000000000)
98-
// => nothing to check
99-
if ($attestationStatement->type === AttestationStatement::TYPE_NONE) {
100-
$this->logger->debug('No attestation returned.');
101-
//No attestation is returned. We shall ensure that the AAGUID is a null one.
102-
//if ($aaguid !== '00000000-0000-0000-0000-000000000000') {
103-
//$this->logger->debug('Anonymization required. AAGUID and Attestation Statement changed.', [
104-
// 'aaguid' => $aaguid,
105-
// 'AttestationStatement' => $attestationStatement,
106-
//]);
107-
//$attestedCredentialData->aaguid = Uuid::fromString('00000000-0000-0000-0000-000000000000');
108-
// return;
109-
//}
94+
95+
/**
96+
* No trust path available for verification
97+
*
98+
* @see https://www.w3.org/TR/webauthn-3/#none
99+
* @see https://www.w3.org/TR/webauthn-3/#self
100+
*/
101+
if (in_array(
102+
$attestationStatement->type,
103+
[AttestationStatement::TYPE_NONE, AttestationStatement::TYPE_SELF],
104+
true
105+
)) {
110106
return;
111107
}
108+
109+
$aaguid = $attestedCredentialData->aaguid
110+
->__toString();
111+
/**
112+
* All-zeros AAGUID: either privacy placeholder or U2F device (which predates AAGUID).
113+
* 1) Privacy Placeholder indicates the authenticator does not provide detailed information.
114+
* 2) U2F device can not provide useful AAGUID.
115+
*
116+
* So Metadata Statement lookup by AAGUID not possible, skip it.
117+
*
118+
* @see https://www.w3.org/TR/webauthn-3/#sctn-createCredential
119+
* @see https://fidoalliance.org/specs/fido-v2.2-ps-20250714/fido-client-to-authenticator-protocol-v2.2-ps-20250714.html#u2f-authenticatorMakeCredential-interoperability
120+
*/
112121
if ($aaguid === '00000000-0000-0000-0000-000000000000') {
113-
//No need to continue if the AAGUID is null.
114-
// This could be the case e.g. with AnonCA type
115122
return;
116123
}
124+
117125
//The MDS Repository is mandatory here
118126
$this->metadataStatementRepository !== null || throw AuthenticatorResponseVerificationException::create(
119127
'The Metadata Statement Repository is mandatory when requesting attestation objects.'
@@ -171,17 +179,13 @@ private function checkStatusReport(string $aaguid): void
171179

172180
private function checkCertificateChain(
173181
AttestationStatement $attestationStatement,
174-
?MetadataStatement $metadataStatement
182+
MetadataStatement $metadataStatement
175183
): void {
176184
$trustPath = $attestationStatement->trustPath;
177-
if (! $trustPath instanceof CertificateTrustPath) {
178-
return;
179-
}
185+
$trustPath instanceof CertificateTrustPath || throw AuthenticatorResponseVerificationException::create(
186+
'Certificate trust path is required for attestation verification'
187+
);
180188
$authenticatorCertificates = $trustPath->certificates;
181-
if ($metadataStatement === null) {
182-
$this->certificateChainValidator?->check($authenticatorCertificates, []);
183-
return;
184-
}
185189
$trustedCertificates = CertificateToolbox::fixPEMStructures(
186190
$metadataStatement->attestationRootCertificates
187191
);

0 commit comments

Comments
 (0)