@@ -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