How to get Forge hosted Laravel application Security Headers perfect
SecurityTo get your security Headers perfect, you'll need the right tools, starting with a scanner.
Use this scanner, before and then after:
https://securityheaders.com/
Before:
Content security is a can of worms but luckily the amazing Spatie has already solved this here.
composer require spatie/laravel-csp
Publish the config-file with:
php artisan vendor:publish --tag=csp-config
This config file is going to make or break your production website. Make sure you have a way to test it!
In our case, where we extensively use Filament, we had to add BunnyFonts:class and quickly uncomment some other directives:
'presets' => [ Spatie\Csp\Presets\Basic::class, Spatie\Csp\Presets\BunnyFonts::class, ], /** * Register additional global CSP directives here. */ 'directives' => [ [Directive::SCRIPT, [Keyword::UNSAFE_EVAL, Keyword::UNSAFE_INLINE]], ],
This did *NOT* work. The reason is you have incredibly carefully test each and every aspect of your website to make sure it's okay.
Here is the `SecureHeaders.php` middleware class:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; class SecureHeaders { /** * Handle an incoming request. * * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next */ public function handle(Request $request, Closure $next): Response { $response = $next($request); $response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains'); $response->headers->set('Referrer-Policy', 'no-referrer-when-downgrade'); $response->headers->set('Permissions-Policy', 'autoplay=(self), camera=(), encrypted-media=(self), fullscreen=(), geolocation=(self), gyroscope=(self), magnetometer=(), microphone=(), midi=(), payment=(), sync-xhr=(self), usb=()'); return $response; } } lang-php
Once you have a working config, you can add the middlewares:
->withMiddleware(function (Middleware $middleware) { $middleware->alias([ 'role' => RoleMiddleware::class, 'permission' => PermissionMiddleware::class, 'role_or_permission' => RoleOrPermissionMiddleware::class, ]); // uncomment after testing each and every aspect of the website! // $middleware->append(AddCspHeaders::class); $middleware->append(SecureHeaders::class); }) lang-php
After (many hours of fiddling):