From edf6af4044b0d781e55f3d29cc3f2534930f3c1c Mon Sep 17 00:00:00 2001 From: gertvanhout Date: Mon, 19 May 2025 09:18:02 +0200 Subject: [PATCH 01/12] - Add storage driver for private key to config - Added private key caching - Improve middleware logic, check if config has minimal values set before trying to sign --- config/cloudfront-cookies.php | 2 ++ .../CloudfrontSignedCookiesMiddleware.php | 5 ++++- src/LaravelCloudfrontCookies.php | 13 ++++++++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/config/cloudfront-cookies.php b/config/cloudfront-cookies.php index fe830fd..db0abcd 100644 --- a/config/cloudfront-cookies.php +++ b/config/cloudfront-cookies.php @@ -11,6 +11,8 @@ 'private_key_path' => env('CLOUDFRONT_PRIVATE_KEY_PATH'), + 'private_key_storage' => env('CLOUDFRONT_PRIVATE_KEY_STORAGE'), + 'domain' => env('CLOUDFRONT_DOMAIN'), 'resource' => env('CLOUDFRONT_RESOURCE', 'http*://localhost/*'), diff --git a/src/Http/Middleware/CloudfrontSignedCookiesMiddleware.php b/src/Http/Middleware/CloudfrontSignedCookiesMiddleware.php index becf21b..0411a6a 100644 --- a/src/Http/Middleware/CloudfrontSignedCookiesMiddleware.php +++ b/src/Http/Middleware/CloudfrontSignedCookiesMiddleware.php @@ -16,7 +16,10 @@ public function handle(Request $request, Closure $next) { $cookies = collect(static::cookieNames()); - $shouldNotSign = $cookies->every(function ($cookie) use ($request) { + $shouldNotSign = config('cloudfront-cookies.resource') === '' || + config('cloudfront-cookies.key_pair_id') === '' || + config('cloudfront-cookies.private_key_path') === '' || + $cookies->every(function ($cookie) use ($request) { return $request->hasCookie($cookie); }); diff --git a/src/LaravelCloudfrontCookies.php b/src/LaravelCloudfrontCookies.php index bfd6e31..b114008 100755 --- a/src/LaravelCloudfrontCookies.php +++ b/src/LaravelCloudfrontCookies.php @@ -7,6 +7,8 @@ use Aws\CloudFront\CloudFrontClient; use Exception; use Illuminate\Support\Carbon; +use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Facades\Storage; class LaravelCloudfrontCookies { @@ -58,9 +60,18 @@ public function policy(?string $policy = null): static public function get(): array { + $private_key = Cache::remember('laravel_cloudfront_cookies_private_key', + 3600 * 24, + fn () => Storage::disk(config('cloudfront-cookies.private_key_storage'))->get(config('cloudfront-cookies.private_key_path')) + ); + + if (! $private_key) { + throw new Exception('private key not found'); + } + return $this->client->getSignedCookie([ 'policy' => $this->policy, - 'private_key' => config('cloudfront-cookies.private_key_path'), + 'private_key' => $private_key, 'key_pair_id' => config('cloudfront-cookies.key_pair_id'), ]); } From 336c48c439edb5d943f0e917b0ee1c344b908cf0 Mon Sep 17 00:00:00 2001 From: GertvHout Date: Mon, 19 May 2025 07:18:49 +0000 Subject: [PATCH 02/12] Fix styling --- src/Http/Middleware/CloudfrontSignedCookiesMiddleware.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Http/Middleware/CloudfrontSignedCookiesMiddleware.php b/src/Http/Middleware/CloudfrontSignedCookiesMiddleware.php index 0411a6a..070acb2 100644 --- a/src/Http/Middleware/CloudfrontSignedCookiesMiddleware.php +++ b/src/Http/Middleware/CloudfrontSignedCookiesMiddleware.php @@ -20,8 +20,8 @@ public function handle(Request $request, Closure $next) config('cloudfront-cookies.key_pair_id') === '' || config('cloudfront-cookies.private_key_path') === '' || $cookies->every(function ($cookie) use ($request) { - return $request->hasCookie($cookie); - }); + return $request->hasCookie($cookie); + }); if ($shouldNotSign) { return $next($request); From b98fe9926be03273a7784b451f209faaa16bd97a Mon Sep 17 00:00:00 2001 From: gertvanhout Date: Mon, 19 May 2025 10:12:44 +0200 Subject: [PATCH 03/12] fix tests --- config/cloudfront-cookies.php | 6 +++--- tests/TestCase.php | 40 +++++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/config/cloudfront-cookies.php b/config/cloudfront-cookies.php index db0abcd..6d5f08e 100644 --- a/config/cloudfront-cookies.php +++ b/config/cloudfront-cookies.php @@ -7,11 +7,11 @@ 'region' => env('CLOUDFRONT_REGION', 'us-east-1'), - 'key_pair_id' => env('CLOUDFRONT_KEY_PAIR_ID'), + 'key_pair_id' => env('CLOUDFRONT_KEY_PAIR_ID', ''), - 'private_key_path' => env('CLOUDFRONT_PRIVATE_KEY_PATH'), + 'private_key_path' => env('CLOUDFRONT_PRIVATE_KEY_PATH', ''), - 'private_key_storage' => env('CLOUDFRONT_PRIVATE_KEY_STORAGE'), + 'private_key_storage' => env('CLOUDFRONT_PRIVATE_KEY_STORAGE', 'local'), 'domain' => env('CLOUDFRONT_DOMAIN'), diff --git a/tests/TestCase.php b/tests/TestCase.php index 6fb2428..2c3e044 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -6,7 +6,9 @@ use Creacoon\LaravelCloudfrontCookies\LaravelCloudfrontCookiesServiceProvider; use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse; use Illuminate\Support\Facades\Route; +use Illuminate\Support\Facades\Storage; use Orchestra\Testbench\TestCase as Orchestra; +use phpDocumentor\Reflection\File; class TestCase extends Orchestra { @@ -31,10 +33,40 @@ protected function getPackageProviders($app): array protected function getEnvironmentSetUp($app): void { - config()->set('services', [ - 'cloudfront' => [ - - ], + $file = + Storage::disk('local')->put('tests/test_private_key.pem', '-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCZBUqdtCv8luW1 +iV3JXPq9IDjKlLvsmnYU7RgZlNfkJpqdM21gDgD2VFM9PQvmSuSsBqLS9E18zs4N +BrQyfXRqGocbhma4W1ZfnX47rELXYMncJTjdc0z6OE+zok7/wpBXZ+IA75t4rGq/ +wCQbKOnz5XQ2QvNzmZEs9WBg7fYWJGrIseJN7/lytMYhdE1HCwwdF2k67ul07rlf +s16IyT99c4OmgzkzhP99UQItmhoHU0fgPmhQ0n01M7O/auE1OM5UHGuMi6559tX6 +UNv8V8R2h/vsqlZS6k7fkNjTlft9Gn3c6MavpK5SV3hhZz+S2BQ22AGIUPmBeFbk +jc49Sr2fAgMBAAECggEABNKqrDD/+FFPoo3wOGbt02tiK6bOC+ilmbmlumiukhce +/tI4IebosNrhJMHGNj2Pp4kuAjTtz3+h9VcljTg9cXquKqsgLn9Y4ZQ2yyEXmjvU +VCDFAg9reORKRTPzn989NwQKY4bDZ7JHfkB+fG/cFj8NKQipk6/4NQQm3YDVvyzd +YYf4cikghy70xurRIBoy2kjkuqYRwKZsPUJ1FWZ22mHDiKJt9F7gfhZEIeK2XZ3X +sIOp5215404k/KecPcXw+fs0TGB4yP0q+/HFNXYa9PJe2CPk+DT9Z3dTnY1DrI0x +KtCVokaSgnYtq35mitLYk5eRQHbtQrWlH9qwo7+HQQKBgQDNIX4Kzt5xtPmE05cn +ei8+M/qPNYItu006szJBXdQAviFMLt2CzIr+v17F6K4ehk84ZmZaw5Ej/Hz/AvgA +N6kA+cPALPtizV045zSQCpbCsSqYQKh4c0hIdMrc/dkiOqOSIWqKKn/BomqowZrv +ugcxuxeC3mcI5OM9IKCo67pXawKBgQC+96RtV5xmllWiI0fTWAwFRj58YhQk+wv3 ++Jz7Rt/lm40rq0IlAHQlNUah+eks1sDGgidFFo2HhqPU6ORkMKZdU0jSF8jD29mR +PMIgnN6ATVSXUHOmb/KhhvChzIHNiI3PLUvQSus45yoRcxLZ6E8spC+7vCKJsQsb +dp0r246jnQKBgQCCMHGIdobjb9K1JH1YhsmZFvA9F97JG4kGaljI973nwsPrUAsy +SpMk31xNC0IHCYMZ7pOjo19okYTbbIztxmWywtIkE+hwappx1PudN7s7UaoQ+2hx +GemUYtulqk621LSfuCmgCx0OTgCXnlixMUYDoBRp8LFACdTXJPAShZm8hQKBgF7e +DTwYcuTvt/jFCBBww//2xmHqI1G/uVFlmy6lJeMdpELWYBSbphc54S3kRbb1tGyp +CbMjogl6lHbXf2ZaWLsx/ZIJKL5LwEiLY3DqHQql3+kPmXRMVr9xlqb6Pl2JgdEz +El+WaEYraFWk0e+YnYRyyBe+PXYjkn4BLdE00CZtAoGBAIQYURPYjEQP+5ptWvyK +eg5yoin/T9dokEOLLflsABVhE+NhRXgsZRurXdD29hbfJlIC3OP2Ry0L9eqs83AQ +XJJYb+eHfJotE3g5AundYSbK4io85p550SgJk+io4ht/Rg8c57KG3J1vqZr7qpwt +aHhk2PE8H+YXPht4mD0Xi85k +-----END PRIVATE KEY-----'); + config()->set('cloudfront-cookies', [ + 'key_pair_id' => 'AA12345678', + 'private_key_path' => 'tests/test_private_key.pem', + 'private_key_storage' => 'local', + 'resource' => '/resource/*', ]); } } From b9152208ed2b689b32d6e3cf4be7c3983e220ca4 Mon Sep 17 00:00:00 2001 From: GertvHout Date: Mon, 19 May 2025 08:13:27 +0000 Subject: [PATCH 04/12] Fix styling --- tests/TestCase.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/TestCase.php b/tests/TestCase.php index 2c3e044..fd0691e 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -8,7 +8,6 @@ use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Storage; use Orchestra\Testbench\TestCase as Orchestra; -use phpDocumentor\Reflection\File; class TestCase extends Orchestra { From 1e9bb06cb7126661c12c7126dfadc7cbc35f96ed Mon Sep 17 00:00:00 2001 From: gertvanhout Date: Mon, 19 May 2025 10:19:09 +0200 Subject: [PATCH 05/12] cleanup --- tests/TestCase.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/TestCase.php b/tests/TestCase.php index fd0691e..01c2fda 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -32,7 +32,6 @@ protected function getPackageProviders($app): array protected function getEnvironmentSetUp($app): void { - $file = Storage::disk('local')->put('tests/test_private_key.pem', '-----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCZBUqdtCv8luW1 iV3JXPq9IDjKlLvsmnYU7RgZlNfkJpqdM21gDgD2VFM9PQvmSuSsBqLS9E18zs4N From 96e60c3e818929c9cb8c8ba56c01971b63fb5dcd Mon Sep 17 00:00:00 2001 From: gertvanhout Date: Fri, 30 May 2025 09:47:05 +0200 Subject: [PATCH 06/12] edit phpstan --- phpstan.neon.dist | 2 -- 1 file changed, 2 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index a91953b..9f85c1e 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -10,5 +10,3 @@ parameters: tmpDir: build/phpstan checkOctaneCompatibility: true checkModelProperties: true - checkMissingIterableValueType: false - From 538234998c3a8901ab9d8680928a97c6643fd0bb Mon Sep 17 00:00:00 2001 From: gertvanhout Date: Fri, 30 May 2025 09:57:22 +0200 Subject: [PATCH 07/12] edit phpstan --- phpstan.neon.dist | 1 - tests/TestCase.php | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 9f85c1e..540131b 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -6,7 +6,6 @@ parameters: paths: - src - config - - database tmpDir: build/phpstan checkOctaneCompatibility: true checkModelProperties: true diff --git a/tests/TestCase.php b/tests/TestCase.php index 01c2fda..31cdef5 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -61,6 +61,7 @@ protected function getEnvironmentSetUp($app): void aHhk2PE8H+YXPht4mD0Xi85k -----END PRIVATE KEY-----'); config()->set('cloudfront-cookies', [ + 'region' => 'us-east-1', 'key_pair_id' => 'AA12345678', 'private_key_path' => 'tests/test_private_key.pem', 'private_key_storage' => 'local', From b9e3354ebdb4871713988d984b76db1ec79b9606 Mon Sep 17 00:00:00 2001 From: gertvanhout Date: Fri, 30 May 2025 10:00:18 +0200 Subject: [PATCH 08/12] Edit config for tests --- tests/TestCase.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/TestCase.php b/tests/TestCase.php index 31cdef5..b5c5a2e 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -61,6 +61,7 @@ protected function getEnvironmentSetUp($app): void aHhk2PE8H+YXPht4mD0Xi85k -----END PRIVATE KEY-----'); config()->set('cloudfront-cookies', [ + 'version' => 'latest', 'region' => 'us-east-1', 'key_pair_id' => 'AA12345678', 'private_key_path' => 'tests/test_private_key.pem', From b9919bd66cf42b0beb124f3bc93111757ee2b2b3 Mon Sep 17 00:00:00 2001 From: gertvanhout Date: Fri, 30 May 2025 10:28:45 +0200 Subject: [PATCH 09/12] Remove domain from config --- config/cloudfront-cookies.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/config/cloudfront-cookies.php b/config/cloudfront-cookies.php index 6d5f08e..804d374 100644 --- a/config/cloudfront-cookies.php +++ b/config/cloudfront-cookies.php @@ -13,8 +13,6 @@ 'private_key_storage' => env('CLOUDFRONT_PRIVATE_KEY_STORAGE', 'local'), - 'domain' => env('CLOUDFRONT_DOMAIN'), - 'resource' => env('CLOUDFRONT_RESOURCE', 'http*://localhost/*'), 'cookies_expiration' => [ From 17d455a56c90a167dee7acd54c7304f3e63fcd3f Mon Sep 17 00:00:00 2001 From: gertvanhout Date: Fri, 30 May 2025 10:47:54 +0200 Subject: [PATCH 10/12] Update Cloudfront cookies config keys and improve middleware condition check --- config/cloudfront-cookies.php | 12 ++++++------ .../Middleware/CloudfrontSignedCookiesMiddleware.php | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/config/cloudfront-cookies.php b/config/cloudfront-cookies.php index 804d374..7b6d210 100644 --- a/config/cloudfront-cookies.php +++ b/config/cloudfront-cookies.php @@ -3,17 +3,17 @@ declare(strict_types=1); return [ - 'version' => env('CLOUDFRONT_VERSION', 'latest'), + 'version' => env('CLOUDFRONT_COOKIES_VERSION', 'latest'), - 'region' => env('CLOUDFRONT_REGION', 'us-east-1'), + 'region' => env('CLOUDFRONT_COOKIES_REGION', 'us-east-1'), - 'key_pair_id' => env('CLOUDFRONT_KEY_PAIR_ID', ''), + 'key_pair_id' => env('CLOUDFRONT_COOKIES_KEY_PAIR_ID'), - 'private_key_path' => env('CLOUDFRONT_PRIVATE_KEY_PATH', ''), + 'private_key_path' => env('CLOUDFRONT_COOKIES_PRIVATE_KEY_PATH'), - 'private_key_storage' => env('CLOUDFRONT_PRIVATE_KEY_STORAGE', 'local'), + 'private_key_storage' => env('CLOUDFRONT_COOKIES_PRIVATE_KEY_STORAGE', 'local'), - 'resource' => env('CLOUDFRONT_RESOURCE', 'http*://localhost/*'), + 'resource' => env('CLOUDFRONT_COOKIES_RESOURCE', 'http*://localhost/*'), 'cookies_expiration' => [ 'unit' => \Carbon\CarbonInterval::PERIOD_DAYS, diff --git a/src/Http/Middleware/CloudfrontSignedCookiesMiddleware.php b/src/Http/Middleware/CloudfrontSignedCookiesMiddleware.php index 070acb2..7b44e21 100644 --- a/src/Http/Middleware/CloudfrontSignedCookiesMiddleware.php +++ b/src/Http/Middleware/CloudfrontSignedCookiesMiddleware.php @@ -16,9 +16,9 @@ public function handle(Request $request, Closure $next) { $cookies = collect(static::cookieNames()); - $shouldNotSign = config('cloudfront-cookies.resource') === '' || - config('cloudfront-cookies.key_pair_id') === '' || - config('cloudfront-cookies.private_key_path') === '' || + $shouldNotSign = !config('cloudfront-cookies.resource') || + !config('cloudfront-cookies.key_pair_id') || + !config('cloudfront-cookies.private_key_path') || $cookies->every(function ($cookie) use ($request) { return $request->hasCookie($cookie); }); From c8570a022fcf8c5a67b14df2fd13fc79470a2509 Mon Sep 17 00:00:00 2001 From: GertvHout Date: Fri, 30 May 2025 08:48:19 +0000 Subject: [PATCH 11/12] Fix styling --- src/Http/Middleware/CloudfrontSignedCookiesMiddleware.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Http/Middleware/CloudfrontSignedCookiesMiddleware.php b/src/Http/Middleware/CloudfrontSignedCookiesMiddleware.php index 7b44e21..56ade9e 100644 --- a/src/Http/Middleware/CloudfrontSignedCookiesMiddleware.php +++ b/src/Http/Middleware/CloudfrontSignedCookiesMiddleware.php @@ -16,9 +16,9 @@ public function handle(Request $request, Closure $next) { $cookies = collect(static::cookieNames()); - $shouldNotSign = !config('cloudfront-cookies.resource') || - !config('cloudfront-cookies.key_pair_id') || - !config('cloudfront-cookies.private_key_path') || + $shouldNotSign = ! config('cloudfront-cookies.resource') || + ! config('cloudfront-cookies.key_pair_id') || + ! config('cloudfront-cookies.private_key_path') || $cookies->every(function ($cookie) use ($request) { return $request->hasCookie($cookie); }); From 4dd8997daf67b159d11f199f9a58ab08f56cae64 Mon Sep 17 00:00:00 2001 From: gertvanhout Date: Fri, 30 May 2025 10:58:24 +0200 Subject: [PATCH 12/12] update README.md --- README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/README.md b/README.md index bbed3ca..d889679 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,34 @@ php artisan vendor:publish --tag="laravel-cloudfront-cookies-views" Add the middleware to set the cookies needed for AWS CloudFront +## Excluding CloudFront Cookies from Laravel Encryption + +Laravel encrypts cookies by default for security. However, CloudFront signed cookies must remain unencrypted to function properly. + +### Configuration Steps + +1. **Locate the EncryptCookies middleware** + - Path: `app/Http/Middleware/EncryptCookies.php` + +2. **Add CloudFront cookies to the exclusion list** + - Update the `$except` array to include the three CloudFront cookie names: + +```php +class EncryptCookies extends Middleware +{ + /** + * The names of the cookies that should not be encrypted. + * + * @var array + */ + protected $except = [ + 'CloudFront-Key-Pair-Id', + 'CloudFront-Policy', + 'CloudFront-Signature', + ]; +} +``` + ## Testing Generate a private key