Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
fix using csp nonce by passing it from the view to the default script…
… tag and added explanations in the readme
  • Loading branch information
Debatty-Tom committed Oct 20, 2025
commit c902ac4d3de469307b815c58336116c66936f65e
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,29 @@ $factors['years'] = [365, 'dayz'];

More information on CarbonInterval's gotchas in [Constantin's blog post on chasingcode.dev](https://chasingcode.dev/blog/carbon-php-practical-examples/).

### Content Security Policy

This package supports CSP nonces for secure script loading. Pass your nonce to the @cookieconsentscripts directive:

```blade
{{-- Basic usage with nonce --}}
@cookieconsentscripts($yourNonce)

{{-- Example with Spatie Laravel CSP --}}
@cookieconsentscripts(app('csp-nonce'))

{{-- Without CSP --}}
@cookieconsentscripts
```

How It Works

When you provide a nonce, it's added to the script tag:

```html
<script src="/cookie-consent-script" nonce="your-nonce-here" defer></script>
```

### Let your users change their mind

Users should be able to change their consent settings at any time. No worries, with this package it is quite simple to achieve: generate a button that will reset the user's cookies and show the consent modal again.
Expand Down
13 changes: 0 additions & 13 deletions config/cookieconsent.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,6 @@

'policy' => null,

/*
|--------------------------------------------------------------------------
| CSP configuration
|--------------------------------------------------------------------------
|
| Most cookie notices display a link to a dedicated page explaining
| the extended cookies usage policy. If your application has such a page
| you can add its route name here.
|
*/

'csp_enable' => env('CSP_ENABLE', false),

/* Google Analytics configuration
|--------------------------------------------------------------------------
|
Expand Down
27 changes: 10 additions & 17 deletions src/CookiesManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,11 @@ protected function makeConsentCookie(): CookieComponent
/**
* Output all the scripts for current consent state.
*/
public function renderScripts(bool $withDefault = true): string
public function renderScripts(bool $withDefault = true, ?string $nonce = null): string
{
$output = $this->shouldDisplayNotice()
? $this->getNoticeScripts($withDefault)
: $this->getConsentedScripts($withDefault);
? $this->getNoticeScripts($withDefault, $nonce)
: $this->getConsentedScripts($withDefault, $nonce);

if(strlen($output)) {
$output = '<!-- Cookie Consent -->' . $output;
Expand All @@ -181,14 +181,14 @@ public function renderScripts(bool $withDefault = true): string
return $output;
}

public function getNoticeScripts(bool $withDefault): string
public function getNoticeScripts(bool $withDefault, ?string $nonce = null): string
{
return $withDefault ? $this->getDefaultScriptTag() : '';
return $withDefault ? $this->getDefaultScriptTag($nonce) : '';
}

protected function getConsentedScripts(bool $withDefault): string
protected function getConsentedScripts(bool $withDefault, ?string $nonce = null): string
{
$output = $this->getNoticeScripts($withDefault);
$output = $this->getNoticeScripts($withDefault, $nonce);

foreach ($this->getConsentResponse()->getResponseScripts() ?? [] as $tag) {
$output .= $tag;
Expand All @@ -197,23 +197,16 @@ protected function getConsentedScripts(bool $withDefault): string
return $output;
}

protected function getDefaultScriptTag(): string
protected function getDefaultScriptTag(?string $nonce = null): string
{
$csp_enable = config('cookieconsent.csp_enable', false);

return '<script '
. 'src="' . route('cookieconsent.script') . '?id='
. md5(\filemtime(LCC_ROOT . '/dist/script.js')) . '" '
. ($csp_enable ? 'nonce="' . $this->generateCspNonce() . '" ' : '')
. md5(\filemtime(LCC_ROOT . '/dist/script.js')) . '" '
. ($nonce ? 'nonce="' . $nonce . '" ' : '')
. 'defer'
. '></script>';
}

protected function generateCspNonce(): string
{
return bin2hex(random_bytes(16));
}

/**
* Output the consent alert/modal for current consent state.
*/
Expand Down
3 changes: 1 addition & 2 deletions src/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,8 @@ public function boot()
protected function registerBladeDirectives()
{
Blade::directive('cookieconsentscripts', function (string $expression) {
return '<?php echo ' . Facades\Cookies::class . '::renderScripts(' . $expression . '); ?>';
return '<?php echo ' . Facades\Cookies::class . '::renderScripts(!empty($expression) ? true, ' . $expression . ' : ""); ?>';
});

Blade::directive('cookieconsentview', function (string $expression) {
return '<?php echo ' . Facades\Cookies::class . '::renderView(); ?>';
});
Expand Down