Files
2FAuth/app/Http/Middleware/AddContentSecurityPolicyHeaders.php

67 lines
2.7 KiB
PHP

<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Vite;
use Symfony\Component\HttpFoundation\Response;
class AddContentSecurityPolicyHeaders
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next) : Response
{
if (config('2fauth.config.contentSecurityPolicy')) {
// Some CSP directives can be used with nonce but not all of them.
// We build a space separated list of addresses to be allowed.
Vite::useCspNonce();
$authorizedAddresses[] = config('app.url') . ':*';
$authorizedAddresses[] = 'https://fastly.jsdelivr.net:*';
// We add custom asset url if defined
if (config('app.asset_url') && config('app.asset_url') != config('app.url')) {
$authorizedAddresses[] = config('app.asset_url') . ':*';
}
// We add 'ws://' protocole and localhost ip address to avoid error with
// Vite hot reload (when running 'npm run dev')
// For the record: 127.0.0.1 is the only supported ip address as CSP
// is intended to work with domain names -it's a www security mecanism)
if (config('app.env') === 'development' && Vite::isRunningHot()) {
$authorizedAddresses[] = 'ws://' . $request->getHttpHost() . ':*';
$authorizedAddresses[] = 'http://127.0.0.1:*';
$authorizedAddresses[] = 'ws://127.0.0.1:*';
}
$authorizedAddresses = implode(' ', $authorizedAddresses);
$directives['script-src'] = "script-src 'nonce-" . Vite::cspNonce() . "' 'wasm-unsafe-eval' 'strict-dynamic'";
$directives['style-src'] = "style-src 'self' " . $authorizedAddresses . " 'unsafe-inline'";
$directives['connect-src'] = "connect-src 'self' " . $authorizedAddresses;
$directives['img-src'] = "img-src 'self' data: " . $authorizedAddresses;
$directives['object-src'] = "object-src 'none'";
$directives['default-src'] = "default-src 'self'";
// This one is to allow eval used by the vue devtools extension
if (config('app.env') === 'development') {
$directives['script-src'] .= " 'unsafe-eval'";
}
$csp = implode('; ', $directives);
/** @disregard Undefined function */
/** @phpstan-ignore-next-line */
return $next($request)->withHeaders([
'Content-Security-Policy' => $csp,
]);
}
return $next($request);
}
}