Skip to content

Commit

Permalink
Merge pull request #198 from creative-commoners/pulls/6/phpunit11
Browse files Browse the repository at this point in the history
DEP Use PHPUnit 11
  • Loading branch information
GuySartorelli authored Sep 18, 2024
2 parents 5be8ef8 + 8322828 commit ce5a03a
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 36 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"guzzlehttp/psr7": "^2"
},
"require-dev": {
"phpunit/phpunit": "^9.6",
"phpunit/phpunit": "^11.3",
"squizlabs/php_codesniffer": "^3",
"silverstripe/documentation-lint": "^1",
"silverstripe/standards": "^1",
Expand Down
5 changes: 5 additions & 0 deletions src/VerifyHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Webauthn\PublicKeyCredentialSource;
use Webauthn\TokenBinding\TokenBindingNotSupportedHandler;
use Cose\Algorithm\Signature\ECDSA\ES256;
use Error;

class VerifyHandler implements VerifyHandlerInterface
{
Expand Down Expand Up @@ -125,6 +126,10 @@ public function verify(HTTPRequest $request, StoreInterface $store, RegisteredMe
private function makeAuthenticatorDataBase64UrlSafe(array $data): array
{
try {
if (!array_key_exists('credentials', $data)) {
// this wil be immediately caught in the catch block below()
throw new Exception();
}
$decodedCredentials = base64_decode($data['credentials']);
$jsonCredientials = json_decode($decodedCredentials, true);
$jsonCredientials['response']['authenticatorData'] = str_replace(
Expand Down
44 changes: 23 additions & 21 deletions tests/RegisterHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
use Webauthn\PublicKeyCredentialLoader;
use Webauthn\PublicKeyCredentialSource;
use Webauthn\TrustPath\EmptyTrustPath;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;

class RegisterHandlerTest extends SapphireTest
{
Expand Down Expand Up @@ -88,8 +90,8 @@ protected function tearDown(): void
/**
* @param string $baseUrl
* @param string $expected
* @dataProvider hostProvider
*/
#[DataProvider('hostProvider')]
public function testRelyingPartyEntityDomainIncludesSilverStripeDomain(string $baseUrl, string $expected)
{
$_SERVER['HTTP_HOST'] = $baseUrl;
Expand All @@ -112,7 +114,7 @@ public function testRelyingPartyEntityDomainIncludesSilverStripeDomain(string $b
/**
* @return array
*/
public function hostProvider(): array
public static function hostProvider(): array
{
return [
'domain only' => ['http://example.com', 'example.com'],
Expand Down Expand Up @@ -167,8 +169,8 @@ public function testRegisterReturnsErrorWhenRequiredInformationIsMissing()
* @param int $expectedCredentialCount
* @param callable $responseValidatorMockCallback
* @throws Exception
* @dataProvider registerProvider
*/
#[DataProvider('registerProvider')]
public function testRegister(
$mockResponse,
$expectedResult,
Expand All @@ -178,7 +180,7 @@ public function testRegister(
) {
/** @var RegisterHandler&MockObject $handlerMock */
$handlerMock = $this->getMockBuilder(RegisterHandler::class)
->setMethods(['getPublicKeyCredentialLoader', 'getAuthenticatorAttestationResponseValidator'])
->onlyMethods(['getPublicKeyCredentialLoader', 'getAuthenticatorAttestationResponseValidator'])
->getMock();

$publicKeyCredentialSourceMock = $this->createMock(PublicKeyCredentialSource::class);
Expand Down Expand Up @@ -233,7 +235,7 @@ public function testRegister(
*
* @return array[]
*/
public function registerProvider()
public static function registerProvider()
{
// phpcs:disable
$testSource = PublicKeyCredentialSource::createFromArray([
Expand All @@ -253,27 +255,27 @@ public function registerProvider()
'counter' => 123456789,
]);
// phpcs:enable

$authDataMock = $this->createMock(AuthenticatorData::class);
$authDataMock->expects($this->exactly(4))->method('hasAttestedCredentialData')
$testCase = new RegisterHandlerTest('MyTestCase');
$authDataMock = $testCase->createMock(AuthenticatorData::class);
$authDataMock->expects($testCase->exactly(4))->method('hasAttestedCredentialData')
// The first call is the "response indicates incomplete data" test case, second is "valid response",
// third is "invalid response"
->willReturnOnConsecutiveCalls(false, true, true, true);
$authDataMock->expects($this->any())->method('getAttestedCredentialData')->willReturn(
$authDataMock->expects($testCase->any())->method('getAttestedCredentialData')->willReturn(
$testSource->getAttestedCredentialData()
);
$authDataMock->expects($this->any())->method('getSignCount')->willReturn(1);
$authDataMock->expects($testCase->any())->method('getSignCount')->willReturn(1);

$attestationMock = $this->createMock(AttestationObject::class);
$attestationMock->expects($this->any())->method('getAuthData')->willReturn($authDataMock);
$attestationMock = $testCase->createMock(AttestationObject::class);
$attestationMock->expects($testCase->any())->method('getAuthData')->willReturn($authDataMock);

$responseMock = $this->createMock(AuthenticatorAttestationResponse::class);
$responseMock->expects($this->any())->method('getAttestationObject')->willReturn($attestationMock);
$responseMock = $testCase->createMock(AuthenticatorAttestationResponse::class);
$responseMock->expects($testCase->any())->method('getAttestationObject')->willReturn($attestationMock);

return [
'wrong response return type' => [
// Deliberately the wrong child implementation of \Webauthn\AuthenticatorResponse
$this->createMock(AuthenticatorAssertionResponse::class),
$testCase->createMock(AuthenticatorAssertionResponse::class),
new Result(false, 'Unexpected response type found'),
0,
],
Expand All @@ -286,10 +288,10 @@ public function registerProvider()
$responseMock,
new Result(true),
1,
function (MockObject $responseValidatorMock) {
function (MockObject $responseValidatorMock) use ($testCase) {
// Specifically setting expectations for the result of the response validator's "check" call
$responseValidatorMock
->expects($this->once())
->expects($testCase->once())
->method('check')
->willReturnCallback(function (): bool {
return true;
Expand All @@ -300,10 +302,10 @@ function (MockObject $responseValidatorMock) {
$responseMock,
new Result(true),
1,
function (MockObject $responseValidatorMock) {
function (MockObject $responseValidatorMock) use ($testCase) {
// Specifically setting expectations for the result of the response validator's "check" call
$responseValidatorMock
->expects($this->once())
->expects($testCase->once())
->method('check')
->willReturnCallback(function (): bool {
return true;
Expand Down Expand Up @@ -336,9 +338,9 @@ function (SessionStore $store) use ($testSource) {
$responseMock,
new Result(false, 'I am a test'),
0,
function (MockObject $responseValidatorMock) {
function (MockObject $responseValidatorMock) use ($testCase) {
// Specifically setting expectations for the result of the response validator's "check" call
$responseValidatorMock->expects($this->once())->method('check')
$responseValidatorMock->expects($testCase->once())->method('check')
->willThrowException(new Exception('I am a test'));
},
],
Expand Down
30 changes: 16 additions & 14 deletions tests/VerifyHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Webauthn\PublicKeyCredentialSource;
use Webauthn\TrustPath\EmptyTrustPath;
use SilverStripe\WebAuthn\ResponseDataException;
use PHPUnit\Framework\Attributes\DataProvider;

class VerifyHandlerTest extends SapphireTest
{
Expand Down Expand Up @@ -123,16 +124,16 @@ public function testVerifyReturnsErrorWhenRequiredInformationIsMissing()
* @param AuthenticatorResponse $mockResponse
* @param Result $expectedResult
* @param callable $responseValidatorMockCallback
* @dataProvider verifyProvider
*/
#[DataProvider('verifyProvider')]
public function testVerify(
$mockResponse,
$expectedResult,
callable $responseValidatorMockCallback = null
) {
/** @var VerifyHandler&MockObject $handlerMock */
$handlerMock = $this->getMockBuilder(VerifyHandler::class)
->setMethods(['getPublicKeyCredentialLoader', 'getAuthenticatorAssertionResponseValidator'])
->onlyMethods(['getPublicKeyCredentialLoader', 'getAuthenticatorAssertionResponseValidator'])
->getMock();

$publicKeyCredentialSourceMock = $this->createMock(PublicKeyCredentialSource::class);
Expand Down Expand Up @@ -178,42 +179,43 @@ public function testVerify(
*
* @return array[]
*/
public function verifyProvider()
public static function verifyProvider()
{
$testCase = new VerifyHandlerTest('MyTestCase');
return [
'wrong response return type' => [
// Deliberately the wrong child implementation of \Webauthn\AuthenticatorResponse
$this->createMock(AuthenticatorAttestationResponse::class),
$testCase->createMock(AuthenticatorAttestationResponse::class),
new Result(false, 'Unexpected response type found'),
],
'valid response' => [
$this->createMock(AuthenticatorAssertionResponse::class),
$testCase->createMock(AuthenticatorAssertionResponse::class),
new Result(true),
function (MockObject $responseValidatorMock) {
function (MockObject $responseValidatorMock) use ($testCase) {
// Specifically setting expectations for the result of the response validator's "check" call
$responseValidatorMock
->expects($this->once())
->expects($testCase->once())
->method('check')
->willReturnCallback(function (): bool {
return true;
});
},
],
'invalid response' => [
$this->createMock(AuthenticatorAssertionResponse::class),
$testCase->createMock(AuthenticatorAssertionResponse::class),
new Result(false, 'I am a test'),
function (MockObject $responseValidatorMock) {
function (MockObject $responseValidatorMock) use ($testCase) {
// Specifically setting expectations for the result of the response validator's "check" call
$responseValidatorMock->expects($this->once())->method('check')
$responseValidatorMock->expects($testCase->once())->method('check')
->willThrowException(new Exception('I am a test'));
},
],
];
}

/**
* @dataProvider provideMakeAuthenticatorDataBase64UrlSafe
*/
#[DataProvider('provideMakeAuthenticatorDataBase64UrlSafe')]
public function testMakeAuthenticatorDataBase64UrlSafe(array $data, string $expected, bool $exception)
{
$reflector = new \ReflectionClass(VerifyHandler::class);
Expand All @@ -232,7 +234,7 @@ public function testMakeAuthenticatorDataBase64UrlSafe(array $data, string $expe
}
}

public function provideMakeAuthenticatorDataBase64UrlSafe(): array
public static function provideMakeAuthenticatorDataBase64UrlSafe(): array
{
$makeData = function ($authenticatorData) {
$a = [];
Expand All @@ -258,12 +260,12 @@ public function provideMakeAuthenticatorDataBase64UrlSafe(): array
'exception' => false,
],
'change slash' => [
'credentials' => $makeData('abc-def/ghi'),
'data' => $makeData('abc-def/ghi'),
'expected' => 'abc-def_ghi',
'exception' => false,
],
'change plus and slash' => [
'credentials' => $makeData('abc+def/ghi'),
'data' => $makeData('abc+def/ghi'),
'expected' => 'abc-def_ghi',
'exception' => false,
],
Expand Down

0 comments on commit ce5a03a

Please sign in to comment.