authenticatorData : $authenticatorResponse->attestationObject->authData; $C = $authenticatorResponse->clientDataJSON; $attestedCredentialData = $publicKeyCredentialSource->getAttestedCredentialData(); $credentialPublicKey = $attestedCredentialData->credentialPublicKey; $credentialPublicKey !== null || throw AuthenticatorResponseVerificationException::create( 'No public key available.' ); $isU2F = U2FPublicKey::isU2FKey($credentialPublicKey); $rpId = $publicKeyCredentialOptions->rpId ?? $publicKeyCredentialOptions->rp->id ?? $host; $facetId = $this->getFacetId($rpId, $publicKeyCredentialOptions->extensions, $authData ->extensions); $rpIdHash = hash('sha256', $isU2F ? $C->origin : $facetId, true); hash_equals( $rpIdHash, $authData ->rpIdHash ) || throw AuthenticatorResponseVerificationException::create('rpId hash mismatch.'); } private function getFacetId( string $rpId, AuthenticationExtensions $authenticationExtensionsClientInputs, null|AuthenticationExtensions $authenticationExtensionsClientOutputs ): string { if ($authenticationExtensionsClientOutputs === null || ! $authenticationExtensionsClientInputs->has( 'appid' ) || ! $authenticationExtensionsClientOutputs->has('appid')) { return $rpId; } $appId = $authenticationExtensionsClientInputs->get('appid') ->value; $wasUsed = $authenticationExtensionsClientOutputs->get('appid') ->value; if (! is_string($appId) || $wasUsed !== true) { return $rpId; } return $appId; } }