Files
michaelschiemer/tests/Framework/Security/RequestSigning/RequestSignerTest.php
Michael Schiemer 55a330b223 Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
2025-08-11 20:13:26 +02:00

139 lines
4.9 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Framework\Security\RequestSigning;
use App\Framework\Http\Headers;
use App\Framework\Http\HttpRequest;
use App\Framework\Http\Method;
use App\Framework\Http\RequestManipulator;
use App\Framework\Security\RequestSigning\RequestSigner;
use App\Framework\Security\RequestSigning\SigningAlgorithm;
use App\Framework\Security\RequestSigning\SigningKey;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
final class RequestSignerTest extends TestCase
{
private RequestSigner $signer;
private RequestManipulator $requestManipulator;
protected function setUp(): void
{
$this->requestManipulator = new RequestManipulator();
$this->signer = new RequestSigner($this->requestManipulator);
}
#[Test]
public function it_can_sign_a_request_with_hmac_sha256(): void
{
$key = SigningKey::createHmac('test-key', 'my-secret-key-that-is-long-enough-for-security');
$request = new HttpRequest(
method: Method::GET,
path: '/api/test',
headers: new Headers(['Host' => 'example.com', 'Date' => 'Thu, 05 Jan 2023 21:31:40 GMT'])
);
$signature = $this->signer->sign($request, $key);
$this->assertEquals('test-key', $signature->keyId);
$this->assertEquals(SigningAlgorithm::HMAC_SHA256, $signature->algorithm);
$this->assertNotEmpty($signature->signature);
$this->assertEquals(['(request-target)', 'host', 'date'], $signature->headers);
}
#[Test]
public function it_can_sign_request_with_custom_headers(): void
{
$key = SigningKey::createHmac('test-key', 'my-secret-key-that-is-long-enough-for-security');
$request = new HttpRequest(
method: Method::POST,
path: '/api/test',
headers: new Headers([
'Host' => 'example.com',
'Date' => 'Thu, 05 Jan 2023 21:31:40 GMT',
'Content-Type' => 'application/json',
]),
body: '{"test": "data"}'
);
$customHeaders = ['(request-target)', 'host', 'date', 'content-type'];
$signature = $this->signer->sign($request, $key, $customHeaders);
$this->assertEquals($customHeaders, $signature->headers);
}
#[Test]
public function it_can_create_digest_for_request_body(): void
{
$body = '{"test": "data"}';
$digest = $this->signer->createDigest($body);
$expectedHash = base64_encode(hash('sha256', $body, true));
$this->assertEquals("SHA256={$expectedHash}", $digest);
}
#[Test]
public function it_can_sign_complete_request_with_body(): void
{
$key = SigningKey::createHmac('test-key', 'my-secret-key-that-is-long-enough-for-security');
$request = new HttpRequest(
method: Method::POST,
path: '/api/test',
headers: new Headers(['Host' => 'example.com']),
body: '{"test": "data"}'
);
$signedRequest = $this->signer->signRequest($request, $key);
// Should have added Date and Digest headers
$this->assertNotNull($signedRequest->headers->getFirst('Date'));
$this->assertNotNull($signedRequest->headers->getFirst('Digest'));
$this->assertNotNull($signedRequest->headers->getFirst('Signature'));
// Digest should be correct
$expectedHash = base64_encode(hash('sha256', $request->body, true));
$this->assertEquals("SHA256={$expectedHash}", $signedRequest->headers->getFirst('Digest'));
}
#[Test]
public function it_throws_exception_for_invalid_key(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Signing key is not valid');
$key = SigningKey::createHmac('expired-key', 'secret-that-is-long-enough-for-security', expiresAt: new \DateTimeImmutable('2020-01-01'));
$request = new HttpRequest(method: Method::GET, path: '/test');
$this->signer->sign($request, $key);
}
#[Test]
public function it_can_generate_rsa_signature(): void
{
// Generate test RSA key pair
$keyPair = openssl_pkey_new([
'digest_alg' => 'sha256',
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
]);
openssl_pkey_export($keyPair, $privateKey);
$key = SigningKey::createRsa('rsa-test-key', $privateKey);
$request = new HttpRequest(
method: Method::GET,
path: '/api/test',
headers: new Headers(['Host' => 'example.com', 'Date' => 'Thu, 05 Jan 2023 21:31:40 GMT'])
);
$signature = $this->signer->sign($request, $key);
$this->assertEquals('rsa-test-key', $signature->keyId);
$this->assertEquals(SigningAlgorithm::RSA_SHA256, $signature->algorithm);
$this->assertNotEmpty($signature->signature);
}
}