diff --git a/src/WebAuthn.php b/src/WebAuthn.php index f2eb755..a15a66e 100644 --- a/src/WebAuthn.php +++ b/src/WebAuthn.php @@ -357,6 +357,12 @@ public function processCreate($clientDataJSON, $attestationObject, $challenge, $ throw new WebAuthnException('invalid origin', WebAuthnException::INVALID_ORIGIN); } + // 6. Verify tokenBinding status (Level 2 §7.1 Step 6). Token Binding is + // deprecated (removed in Level 3), so reject "present" since we cannot verify it. + if (\property_exists($clientData, 'tokenBinding') && \is_object($clientData->tokenBinding) && \property_exists($clientData->tokenBinding, 'status') && $clientData->tokenBinding->status === 'present') { + throw new WebAuthnException('token binding not supported', WebAuthnException::INVALID_DATA); + } + // Attestation $attestationObject = new Attestation\AttestationObject($attestationObject, $this->_formats); @@ -475,6 +481,12 @@ public function processGet($clientDataJSON, $authenticatorData, $signature, $cre throw new WebAuthnException('invalid origin', WebAuthnException::INVALID_ORIGIN); } + // 10. Verify tokenBinding status (Level 2 §7.2 Step 10). Token Binding is + // deprecated (removed in Level 3), so reject "present" since we cannot verify it. + if (\property_exists($clientData, 'tokenBinding') && \is_object($clientData->tokenBinding) && \property_exists($clientData->tokenBinding, 'status') && $clientData->tokenBinding->status === 'present') { + throw new WebAuthnException('token binding not supported', WebAuthnException::INVALID_DATA); + } + // 11. Verify that the rpIdHash in authData is the SHA-256 hash of the RP ID expected by the Relying Party. if ($authenticatorObj->getRpIdHash() !== $this->_rpIdHash) { throw new WebAuthnException('invalid rpId hash', WebAuthnException::INVALID_RELYING_PARTY);