From b7c8531f1c3b9d59c28173e352f856560b345dbf Mon Sep 17 00:00:00 2001 From: Scott Helme Date: Fri, 27 Mar 2026 23:08:58 +0000 Subject: [PATCH] Reject token binding status present in processCreate and processGet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per Level 2 spec (§7.1 Step 6, §7.2 Step 10), if tokenBinding.status is "present" the server must verify the binding ID against the TLS connection. Since the library does not implement Token Binding (which is deprecated and removed from Level 3), reject "present" rather than silently accepting an unverifiable claim. The "supported" status is still accepted — it simply means the browser supports Token Binding but did not use it for this connection. Fixes lbuchs/WebAuthn#130 --- src/WebAuthn.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) 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);