Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 6 additions & 6 deletions config/cloudfront-cookies.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'),

'domain' => env('CLOUDFRONT_DOMAIN'),
'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,
Expand Down
3 changes: 0 additions & 3 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ parameters:
paths:
- src
- config
- database
tmpDir: build/phpstan
checkOctaneCompatibility: true
checkModelProperties: true
checkMissingIterableValueType: false

9 changes: 6 additions & 3 deletions src/Http/Middleware/CloudfrontSignedCookiesMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ public function handle(Request $request, Closure $next)
{
$cookies = collect(static::cookieNames());

$shouldNotSign = $cookies->every(function ($cookie) use ($request) {
return $request->hasCookie($cookie);
});
$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);
});

if ($shouldNotSign) {
return $next($request);
Expand Down
13 changes: 12 additions & 1 deletion src/LaravelCloudfrontCookies.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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'),
]);
}
Expand Down
40 changes: 36 additions & 4 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
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;

class TestCase extends Orchestra
Expand All @@ -31,10 +32,41 @@ protected function getPackageProviders($app): array

protected function getEnvironmentSetUp($app): void
{
config()->set('services', [
'cloudfront' => [

],
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', [
'version' => 'latest',
'region' => 'us-east-1',
'key_pair_id' => 'AA12345678',
'private_key_path' => 'tests/test_private_key.pem',
'private_key_storage' => 'local',
'resource' => '/resource/*',
]);
}
}