SecurityHeaders.php 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. <?php
  2. namespace Webkul\BagistoApi\Http\Middleware;
  3. use Closure;
  4. use Illuminate\Http\Request;
  5. /**
  6. * Adds essential HTTP security headers to API responses
  7. */
  8. class SecurityHeaders
  9. {
  10. public function handle(Request $request, Closure $next)
  11. {
  12. $response = $next($request);
  13. if (! $this->isApiRequest($request)) {
  14. return $response;
  15. }
  16. $this->addSecurityHeaders($response);
  17. return $response;
  18. }
  19. private function isApiRequest(Request $request): bool
  20. {
  21. return str_starts_with($request->path(), 'api/');
  22. }
  23. private function addSecurityHeaders($response): void
  24. {
  25. $headers = [
  26. 'X-Content-Type-Options' => 'nosniff',
  27. 'X-Frame-Options' => 'DENY',
  28. 'X-XSS-Protection' => '1; mode=block',
  29. 'Referrer-Policy' => 'strict-origin-when-cross-origin',
  30. 'Permissions-Policy' => 'geolocation=(), microphone=(), camera=(), payment=(), usb=(), magnetometer=(), gyroscope=(), accelerometer=()',
  31. 'Content-Security-Policy' => $this->getCSPHeader(),
  32. ];
  33. if ($this->shouldUseHSTS()) {
  34. $headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains; preload';
  35. }
  36. foreach ($headers as $key => $value) {
  37. $response->headers->set($key, $value);
  38. }
  39. }
  40. private function shouldUseHSTS(): bool
  41. {
  42. return app()->environment('production') || config('api-platform.force_https', false);
  43. }
  44. private function getCSPHeader(): string
  45. {
  46. $defaultCSP = "default-src 'self'; "
  47. ."script-src 'self' 'unsafe-inline' 'unsafe-eval'; "
  48. ."style-src 'self' 'unsafe-inline'; "
  49. ."img-src 'self' data: https:; "
  50. ."font-src 'self'; "
  51. ."connect-src 'self'; "
  52. ."frame-ancestors 'none'; "
  53. ."base-uri 'self'; "
  54. ."form-action 'self'";
  55. return config('api-platform.csp_header', $defaultCSP);
  56. }
  57. }