Skip to content

Commit

Permalink
Merge pull request #435 from joostdebruijn/fix/add-transports
Browse files Browse the repository at this point in the history
fix: return transports in attestation response pk credential source
  • Loading branch information
Spomky authored Jul 15, 2023
2 parents 69c7a16 + c3eae17 commit ca754d8
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 8 deletions.
14 changes: 13 additions & 1 deletion src/webauthn/src/AuthenticatorAttestationResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@
*/
class AuthenticatorAttestationResponse extends AuthenticatorResponse
{
/**
* @param string[] $transports
*/
public function __construct(
CollectedClientData $clientDataJSON,
private readonly AttestationObject $attestationObject
private readonly AttestationObject $attestationObject,
private readonly array $transports = []
) {
parent::__construct($clientDataJSON);
}
Expand All @@ -22,4 +26,12 @@ public function getAttestationObject(): AttestationObject
{
return $this->attestationObject;
}

/**
* @return string[]
*/
public function getTransports(): array
{
return $this->transports;
}
}
11 changes: 8 additions & 3 deletions src/webauthn/src/AuthenticatorAttestationResponseValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,8 @@ public function check(
$attestedCredentialData,
$attestationObject,
$publicKeyCredentialCreationOptions->getUser()
->getId()
->getId(),
$authenticatorAttestationResponse->getTransports()
);
$this->logger->info('The attestation is valid');
$this->logger->debug('Public Key Credential Source', [
Expand Down Expand Up @@ -471,11 +472,15 @@ private function checkStatusReport(string $aaguid): void
}
}

/**
* @param string[] $transports
*/
private function createPublicKeyCredentialSource(
string $credentialId,
AttestedCredentialData $attestedCredentialData,
AttestationObject $attestationObject,
string $userHandle
string $userHandle,
array $transports
): PublicKeyCredentialSource {
$credentialPublicKey = $attestedCredentialData->getCredentialPublicKey();
$credentialPublicKey !== null || throw AuthenticatorResponseVerificationException::create(
Expand All @@ -484,7 +489,7 @@ private function createPublicKeyCredentialSource(
return new PublicKeyCredentialSource(
$credentialId,
PublicKeyCredentialDescriptor::CREDENTIAL_TYPE_PUBLIC_KEY,
[],
$transports,
$attestationObject->getAttStmt()
->getType(),
$attestationObject->getAttStmt()
Expand Down
8 changes: 7 additions & 1 deletion src/webauthn/src/PublicKeyCredentialLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ private function createResponse(array $response): AuthenticatorResponse
$response,
'Invalid data. The parameter "userHandle" is invalid'
);
/** @var string[] $transports */
$transports = $response['transports'] ?? [];
is_array($transports) || throw InvalidDataException::create(
$response,
'Invalid data. The parameter "transports" is invalid'
);
switch (true) {
case array_key_exists('attestationObject', $response):
is_string($response['attestationObject']) || throw InvalidDataException::create(
Expand All @@ -151,7 +157,7 @@ private function createResponse(array $response): AuthenticatorResponse

return new AuthenticatorAttestationResponse(CollectedClientData::createFormJson(
$response['clientDataJSON']
), $attestationObject);
), $attestationObject, $transports);
case array_key_exists('authenticatorData', $response) && array_key_exists('signature', $response):
$authData = Base64UrlSafe::decodeNoPadding($response['authenticatorData']);

Expand Down
9 changes: 6 additions & 3 deletions tests/library/Functional/AttestationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,21 @@ public function anAttestationSignedWithEcDSA521ShouldBeVerified(): void
$publicKeyCredentialDescriptor = null;
$authenticatorData = null;
$options = '{"rp":{"name":"Webauthn Demo","id":"webauthn.spomky-labs.com"},"pubKeyCredParams":[{"type":"public-key","alg":-8},{"type":"public-key","alg":-7},{"type":"public-key","alg":-46},{"type":"public-key","alg":-35},{"type":"public-key","alg":-36},{"type":"public-key","alg":-257},{"type":"public-key","alg":-258},{"type":"public-key","alg":-259},{"type":"public-key","alg":-37},{"type":"public-key","alg":-38},{"type":"public-key","alg":-39}],"challenge":"MJr5sD0WitVwZM0eoSO6kWhyseT67vc3oQdk_k1VdZQ","attestation":"direct","user":{"name":"zOEOkAZGg3ZrD8l_TFwD","id":"ZDYzNGZlZGQtMGZiNi00ZDY3LWI5OGEtNDk2OWY2ZTMwNTY1","displayName":"Shenika Olin"},"authenticatorSelection":{"requireResidentKey":false,"userVerification":"preferred"},"timeout":60000}';
$response = '{"id":"R4fAVj9osgVVZL7yHftPeVOmjom3xw4ZLK7Dt_8mzOM","rawId":"R4fAVj9osgVVZL7yHftPeVOmjom3xw4ZLK7Dt/8mzOM","response":{"attestationObject":"o2NmbXRmcGFja2VkZ2F0dFN0bXSiY2FsZzgjY3NpZ1iLMIGIAkIA-KkXe-BmfxZgJNet2JPOZ6-fjPQskjnqOYWf7LW2iMFDbbZ3_oU18m0IGVksCPOaSsDs6MC14CQSqcQpvo0YxHMCQgFKm882cBfrPs4zM7piS3bM3yG6W4OrS9bbIj34e7b9JNH0Ee-w0cAeUaxQNyyedC4y4fSqvUjDT0f0Mj-iE0-pa2hhdXRoRGF0YVjplgTqgoJOmKStoUtEYtDXOo7EaRMNqRsZMHRZIp90o1lBAAAAlSOIq42JFUFGk7rUPmcdJTgAIEeHwFY_aLIFVWS-8h37T3lTpo6Jt8cOGSyuw7f_JszjpQECAzgjIAMhWEIA6Q6fXXQzt2RH6cq4eKJpfFU4nhmCWH2DKAa33T-uGStxA0zaA3goYphgRW6PkgyETh-Q4I3-NJ6KCx-5QV39v50iWEIAA9xyNnqltQaG2UuiLtuSNM59PLv3skYKKmnAvUDT7J6YwPwVyzOWKOyIfgQc9oPO9dRQ21Da498iOhx5qA5gbRo","clientDataJSON":"eyJvcmlnaW4iOiJodHRwczovL3dlYmF1dGhuLnNwb21reS1sYWJzLmNvbSIsImNoYWxsZW5nZSI6Ik1KcjVzRDBXaXRWd1pNMGVvU082a1doeXNlVDY3dmMzb1Fka19rMVZkWlEiLCJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIn0"},"type":"public-key"}';
$response = '{"id":"R4fAVj9osgVVZL7yHftPeVOmjom3xw4ZLK7Dt_8mzOM","rawId":"R4fAVj9osgVVZL7yHftPeVOmjom3xw4ZLK7Dt/8mzOM","response":{"attestationObject":"o2NmbXRmcGFja2VkZ2F0dFN0bXSiY2FsZzgjY3NpZ1iLMIGIAkIA-KkXe-BmfxZgJNet2JPOZ6-fjPQskjnqOYWf7LW2iMFDbbZ3_oU18m0IGVksCPOaSsDs6MC14CQSqcQpvo0YxHMCQgFKm882cBfrPs4zM7piS3bM3yG6W4OrS9bbIj34e7b9JNH0Ee-w0cAeUaxQNyyedC4y4fSqvUjDT0f0Mj-iE0-pa2hhdXRoRGF0YVjplgTqgoJOmKStoUtEYtDXOo7EaRMNqRsZMHRZIp90o1lBAAAAlSOIq42JFUFGk7rUPmcdJTgAIEeHwFY_aLIFVWS-8h37T3lTpo6Jt8cOGSyuw7f_JszjpQECAzgjIAMhWEIA6Q6fXXQzt2RH6cq4eKJpfFU4nhmCWH2DKAa33T-uGStxA0zaA3goYphgRW6PkgyETh-Q4I3-NJ6KCx-5QV39v50iWEIAA9xyNnqltQaG2UuiLtuSNM59PLv3skYKKmnAvUDT7J6YwPwVyzOWKOyIfgQc9oPO9dRQ21Da498iOhx5qA5gbRo","clientDataJSON":"eyJvcmlnaW4iOiJodHRwczovL3dlYmF1dGhuLnNwb21reS1sYWJzLmNvbSIsImNoYWxsZW5nZSI6Ik1KcjVzRDBXaXRWd1pNMGVvU082a1doeXNlVDY3dmMzb1Fka19rMVZkWlEiLCJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIn0","transports":["usb"]},"type":"public-key"}';
$publicKeyCredentialCreationOptions = PublicKeyCredentialCreationOptions::createFromString($options);
$publicKeyCredential = $this->getPublicKeyCredentialLoader()
->load($response);
static::assertInstanceOf(AuthenticatorAttestationResponse::class, $publicKeyCredential->getResponse());
$this->getAuthenticatorAttestationResponseValidator()
$publicKeyCredentialSource = $this->getAuthenticatorAttestationResponseValidator()
->check(
$publicKeyCredential->getResponse(),
$publicKeyCredentialCreationOptions,
'webauthn.spomky-labs.com'
);
$publicKeyCredentialDescriptor = $publicKeyCredential->getPublicKeyCredentialDescriptor(['usb']);
static::assertSame(['usb'], $publicKeyCredentialSource->getTransports());
$publicKeyCredentialDescriptor = $publicKeyCredential->getPublicKeyCredentialDescriptor(
$publicKeyCredentialSource->getTransports()
);
static::assertSame(
hex2bin('4787c0563f68b2055564bef21dfb4f7953a68e89b7c70e192caec3b7ff26cce3'),
Base64UrlSafe::decode($publicKeyCredential->getId())
Expand Down

0 comments on commit ca754d8

Please sign in to comment.