Skip to content

Commit

Permalink
Content Security Policy Support (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
rawilk authored Apr 14, 2023
1 parent 7447443 commit 344ea7d
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 3 deletions.
28 changes: 25 additions & 3 deletions src/Support/WebauthnAssets.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Rawilk\Webauthn\Support;

use Illuminate\Support\Facades\Vite;

class WebauthnAssets
{
public function javaScript(array $options = []): string
Expand All @@ -17,15 +19,35 @@ public function javaScript(array $options = []): string

private function javaScriptAssets(array $options = []): string
{
$appUrl = config('webauthn.asset_url', rtrim($options['asset_url'] ?? '', '/'));
$assetsUrl = config('webauthn.asset_url') ?: rtrim($options['asset_url'] ?? '', '/');
$nonce = $this->getNonce($options);

$manifest = json_decode(file_get_contents(__DIR__ . '/../../dist/mix-manifest.json'), true);
$versionedFileName = ltrim($manifest['/assets/webauthn.js'], '/');

$fullAssetPath = "{$appUrl}/webauthn/{$versionedFileName}";
$fullAssetPath = "{$assetsUrl}/webauthn/{$versionedFileName}";

return <<<HTML
<script src="{$fullAssetPath}" data-turbolinks-eval="false" data-turbo-eval="false"></script>
<script src="{$fullAssetPath}" data-turbolinks-eval="false" data-turbo-eval="false" {$nonce}></script>
HTML;
}

private function getNonce(array $options): string
{
if (isset($options['nonce'])) {
return "nonce=\"{$options['nonce']}\"";
}

// If there is a csp package installed, i.e. spatie/laravel-csp, we'll check for the existence of the helper function.
if (function_exists('csp_nonce') && $nonce = csp_nonce()) {
return "nonce=\"{$nonce}\"";
}

// Lastly, we'll check for the existence of a csp nonce from Vite.
if (class_exists(Vite::class) && $nonce = Vite::cspNonce()) {
return "nonce=\"{$nonce}\"";
}

return '';
}
}
1 change: 1 addition & 0 deletions tests/Pest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
uses(TestCase::class)->in(
__DIR__ . '/Models',
__DIR__ . '/Services',
__DIR__ . '/Unit',
);

// Helpers
Expand Down
59 changes: 59 additions & 0 deletions tests/Unit/AssetsDirectiveTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);

use Rawilk\Webauthn\Support\WebauthnAssets;

beforeEach(function () {
$this->assets = new WebauthnAssets;
});

it('outputs the script source', function () {
$this->assertStringContainsString(
'<script src="/webauthn/assets/webauthn.js?',
$this->assets->javaScript(),
);
});

it('outputs a comment when app is in debug mode', function () {
config()->set('app.debug', true);

$this->assertStringContainsString(
'<!-- WebAuthn Scripts -->',
$this->assets->javaScript(),
);
});

it('does not output a comment when not in debug mode', function () {
config()->set('app.debug', false);

$this->assertStringNotContainsString(
'<!-- WebAuthn Scripts -->',
$this->assets->javaScript(),
);
});

it('can use a custom asset url', function () {
config()->set('webauthn.asset_url', 'https://example.com');

$this->assertStringContainsString(
'<script src="https://example.com/webauthn/assets/webauthn.js?',
$this->assets->javaScript(),
);
});

it('accepts an asset url as an argument', function () {
$this->assertStringContainsString(
'<script src="https://example.com/webauthn/assets/webauthn.js?',
$this->assets->javaScript(['asset_url' => 'https://example.com']),
);
});

it('can output a nonce on the script tag', function () {
$nonce = Str::random(32);

$this->assertStringContainsString(
"nonce=\"{$nonce}\"",
$this->assets->javaScript(['nonce' => $nonce]),
);
});

0 comments on commit 344ea7d

Please sign in to comment.