Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
SecureHeaders
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 2
30
0.00% covered (danger)
0.00%
0 / 1
 handle
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
12
 removeUnwantedHeaders
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace App\Http\Middleware;
4
5use Closure;
6use Illuminate\Http\Request;
7use Illuminate\Support\Facades\Route;
8use Illuminate\Support\Facades\View;
9use Symfony\Component\HttpFoundation\Response;
10
11class SecureHeaders
12{
13    /**
14     * Enumerate headers which you do not want in your application's responses.
15     * Great starting point would be to go check out @Scott_Helme's:
16     * https://securityheaders.com/
17     *
18     * @var array
19     */
20    private $unwantedHeaderList = [
21        'X-Powered-By',
22        'Server',
23    ];
24
25    /**
26     * Handle an incoming request.
27     *
28     * @param  \Illuminate\Http\Request                                                         $request
29     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
30     * @return \Symfony\Component\HttpFoundation\Response
31     * @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
32     */
33    public function handle(Request $request, Closure $next): Response
34    {
35        // phpcs:enable
36        View::share('nonce', $nonce = \uniqid());
37        // * For VueJS dev tool to execute
38        $jsDev     = config('app.debug') ? "'unsafe-eval' 'unsafe-inline'" : "'nonce-{$nonce}' 'strict-dynamic'";
39        $reportUri = Route::has('cspReportUri') ?
40            \sprintf(' report-uri %s ;', \parse_url(route('cspReportUri'), \PHP_URL_PATH)) : '';
41        $this->removeUnwantedHeaders($this->unwantedHeaderList);
42        $response = $next($request);
43        $response->headers->set('Referrer-Policy', 'no-referrer-when-downgrade');
44        $response->headers->set('X-Content-Type-Options', 'nosniff');
45        $response->headers->set('X-XSS-Protection', '1; mode=block');
46        $response->headers->set('X-Frame-Options', 'SAMEORIGIN');
47        $response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains;');
48        $cspPolicies = [
49            "manifest-src 'self';",
50            "connect-src 'self' blob:;",
51            "img-src * data: blob:;",
52            "font-src 'self' data: https://fonts.gstatic.com;",
53            "style-src 'self' 'unsafe-inline';",
54            "script-src 'self' {$jsDev} " . \implode(' ', [
55                'https:  blob:',
56            ]) . ';'
57        ];
58
59        $response->headers->set(
60            'Content-Security-Policy',
61            implode(' ', $cspPolicies) . $reportUri
62        );
63        $response->headers->set('Feature-Policy', 'fullscreen \'self\';');
64        return $response;
65    }
66
67    /**
68     * Remove unwanted headers
69     *
70     * @param array $headerList
71     * @return void
72     */
73    private function removeUnwantedHeaders(array $headerList)
74    {
75        foreach ($headerList as $header) {
76            header_remove($header);
77        }
78    }
79}