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:
Here is the `SecureHeaders.php` middleware class for a fairly vanilla Filament PHP site with some jQuery in the mix
The key to sanity was the last response to do the content. By having it nicely formatted we could slowly but surely trawl our site and make the corrections required.
<?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=()'); $cspWithNewlines = " default-src 'self'; script-src 'self' cdn.jsdelivr.net platform.twitter.com 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline' fonts.bunny.net cdn.jsdelivr.net fonts.googleapis.com; img-src 'self' * data:; font-src 'self' data: fonts.bunny.net cdn.jsdelivr.net fonts.gstatic.com; connect-src 'self'; media-src 'self'; frame-src 'self' *.bunny.net *.jsdelivr.net platform.twitter.com github.com *.youtube.com *.vimeo.com; object-src 'none'; base-uri 'self'; report-uri "; $response->headers->set('Content-Security-Policy', str_replace("\n", '', $cspWithNewlines)); 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, ]); $middleware->append(SecureHeaders::class); }) lang-php
After (many hours of fiddling):
- https://danieldusek.com/enabling-security-headers-for-your-website-with-php-and-laravel.html
- https://dcblog.dev/laravel-security-headers
A special mention also to Spatie who has https://github.com/spatie/laravel-csp. I couldn't get it working so reverted to output with newlines.