197 lines
7.2 KiB
PHP
197 lines
7.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Unit\Infra\Adapters\Services;
|
|
|
|
use Application\Security\Models\Entities\Client;
|
|
use Application\Security\Models\ValueObjects\ClientIdentifier;
|
|
use Application\Security\Models\ValueObjects\ClientName;
|
|
use Application\Security\Models\ValueObjects\ClientSecret;
|
|
use Application\Security\Models\ValueObjects\Entities\ClientId;
|
|
use Application\Security\Models\ValueObjects\Request\HttpMethod;
|
|
use Application\Security\Models\ValueObjects\Request\Nonce;
|
|
use Application\Security\Models\ValueObjects\Request\Request;
|
|
use Application\Security\Models\ValueObjects\Request\RequestSignature;
|
|
use Application\Security\Models\ValueObjects\Request\RequestTimestamp;
|
|
use Application\Security\Ports\Repositories\ClientRepository;
|
|
use Application\Security\Ports\Services\HmacSignatureValidator;
|
|
use Application\Security\Ports\Services\NonceValidator;
|
|
use Application\Security\Ports\Services\RequestValidation\RequestValidationStatus;
|
|
use Application\Security\Ports\Services\TimestampValidator;
|
|
use DateTimeImmutable;
|
|
use Infra\Adapters\Services\RequestValidatorImpl;
|
|
use Mockery;
|
|
use Psr\Log\NullLogger;
|
|
use Ramsey\Uuid\Uuid;
|
|
use Uri\Rfc3986\Uri;
|
|
|
|
covers(RequestValidatorImpl::class);
|
|
|
|
describe('RequestValidatorImpl Unit Tests', function (): void {
|
|
it('returns valid result when all security checks pass', function (): void {
|
|
// GIVEN
|
|
$logger = new NullLogger();
|
|
$signatureValidator = Mockery::mock(HmacSignatureValidator::class);
|
|
$nonceValidator = Mockery::mock(NonceValidator::class);
|
|
$timestampValidator = Mockery::mock(TimestampValidator::class);
|
|
$clientRepository = Mockery::mock(ClientRepository::class);
|
|
|
|
$validator = new RequestValidatorImpl(
|
|
$logger,
|
|
$signatureValidator,
|
|
$nonceValidator,
|
|
$timestampValidator,
|
|
$clientRepository
|
|
);
|
|
|
|
$clientIdentifier = new ClientIdentifier('arcadia_id_' . str_repeat('a', 32));
|
|
$clientSecret = new ClientSecret('arcadia_sec_' . str_repeat('b', 86));
|
|
$client = Client::hydrate(
|
|
id: new ClientId(Uuid::uuid7()),
|
|
name: new ClientName('Test Client'),
|
|
identifier: $clientIdentifier,
|
|
secret: $clientSecret,
|
|
isActive: true,
|
|
updatedAt: new DateTimeImmutable(),
|
|
);
|
|
|
|
$request = new Request(
|
|
uri: new Uri('http://localhost/api/v1/test'),
|
|
method: HttpMethod::GET,
|
|
bodyHash: null,
|
|
signature: new RequestSignature(str_repeat('a', 64)),
|
|
nonce: new Nonce(Uuid::uuid7()),
|
|
identifier: $clientIdentifier,
|
|
timestamp: new RequestTimestamp(new DateTimeImmutable()),
|
|
);
|
|
|
|
$clientRepository->expects('findByIdentifier')
|
|
->with($clientIdentifier)
|
|
->andReturn($client);
|
|
|
|
$timestampValidator->expects('validate')
|
|
->once()
|
|
->andReturn(true);
|
|
|
|
$signatureValidator->expects('validate')
|
|
->once()
|
|
->with($request, $clientSecret)
|
|
->andReturn(true);
|
|
|
|
$nonceValidator->expects('validateAndConsume')
|
|
->once()
|
|
->with($request->nonce, $clientIdentifier)
|
|
->andReturn(true);
|
|
|
|
// WHEN
|
|
$result = $validator->validate($request);
|
|
|
|
// THEN
|
|
expect($result->isValid())->toBeTrue()
|
|
->and($result->status)->toBe(RequestValidationStatus::VALID)
|
|
->and($result->client)->toBe($client);
|
|
});
|
|
|
|
it('returns client not found when client does not exist', function (): void {
|
|
// GIVEN
|
|
$logger = new NullLogger();
|
|
$signatureValidator = Mockery::mock(HmacSignatureValidator::class);
|
|
$nonceValidator = Mockery::mock(NonceValidator::class);
|
|
$timestampValidator = Mockery::mock(TimestampValidator::class);
|
|
$clientRepository = Mockery::mock(ClientRepository::class);
|
|
|
|
$validator = new RequestValidatorImpl(
|
|
$logger,
|
|
$signatureValidator,
|
|
$nonceValidator,
|
|
$timestampValidator,
|
|
$clientRepository
|
|
);
|
|
|
|
$clientIdentifier = new ClientIdentifier('arcadia_id_' . str_repeat('a', 32));
|
|
$request = new Request(
|
|
uri: new Uri('http://localhost/api/v1/test'),
|
|
method: HttpMethod::GET,
|
|
bodyHash: null,
|
|
signature: new RequestSignature(str_repeat('a', 64)),
|
|
nonce: new Nonce(Uuid::uuid7()),
|
|
identifier: $clientIdentifier,
|
|
timestamp: new RequestTimestamp(new DateTimeImmutable()),
|
|
);
|
|
|
|
$clientRepository->expects('findByIdentifier')
|
|
->with($clientIdentifier)
|
|
->andReturn(null);
|
|
|
|
$timestampValidator->expects('validate')
|
|
->once()
|
|
->andReturn(true);
|
|
|
|
// WHEN
|
|
$result = $validator->validate($request);
|
|
|
|
// THEN
|
|
expect($result->isValid())->toBeFalse()
|
|
->and($result->status)->toBe(RequestValidationStatus::CLIENT_NOT_FOUND)
|
|
->and($result->client)->toBeNull();
|
|
});
|
|
|
|
it('returns client not authorized when client is inactive', function (): void {
|
|
// GIVEN
|
|
$logger = new NullLogger();
|
|
$signatureValidator = Mockery::mock(HmacSignatureValidator::class);
|
|
$nonceValidator = Mockery::mock(NonceValidator::class);
|
|
$timestampValidator = Mockery::mock(TimestampValidator::class);
|
|
$clientRepository = Mockery::mock(ClientRepository::class);
|
|
|
|
$validator = new RequestValidatorImpl(
|
|
$logger,
|
|
$signatureValidator,
|
|
$nonceValidator,
|
|
$timestampValidator,
|
|
$clientRepository
|
|
);
|
|
|
|
$clientIdentifier = new ClientIdentifier('arcadia_id_' . str_repeat('a', 32));
|
|
$clientSecret = new ClientSecret('arcadia_sec_' . str_repeat('b', 86));
|
|
$client = Client::hydrate(
|
|
id: new ClientId(Uuid::uuid7()),
|
|
name: new ClientName('Inactive Client'),
|
|
identifier: $clientIdentifier,
|
|
secret: $clientSecret,
|
|
isActive: false,
|
|
updatedAt: new DateTimeImmutable(),
|
|
);
|
|
|
|
$request = new Request(
|
|
uri: new Uri('http://localhost/api/v1/test'),
|
|
method: HttpMethod::GET,
|
|
bodyHash: null,
|
|
signature: new RequestSignature(str_repeat('a', 64)),
|
|
nonce: new Nonce(Uuid::uuid7()),
|
|
identifier: $clientIdentifier,
|
|
timestamp: new RequestTimestamp(new DateTimeImmutable()),
|
|
);
|
|
|
|
$clientRepository->expects('findByIdentifier')
|
|
->with($clientIdentifier)
|
|
->andReturn($client);
|
|
|
|
$timestampValidator->expects('validate')
|
|
->once()
|
|
->andReturn(true);
|
|
|
|
$signatureValidator->expects('validate')
|
|
->once()
|
|
->with($request, $clientSecret)
|
|
->andReturn(true);
|
|
|
|
// WHEN
|
|
$result = $validator->validate($request);
|
|
|
|
// THEN
|
|
expect($result->isValid())->toBeFalse()
|
|
->and($result->status)->toBe(RequestValidationStatus::CLIENT_NOT_AUTHORIZED);
|
|
});
|
|
});
|