Aller au contenu
Patrick Junod Patrick Junod

Gestion des CORS sur Laravel via un Middleware

Découvrez dans cet article une solution simple et pratique pour gérer vos CORS facilement sur une installation Laravel.

La sécurité est un aspect crucial du développement web moderne, particulièrement lorsqu'il s'agit de gérer les requêtes cross-origin (CORS). Dans cet article, nous allons explorer comment implémenter une solution robuste de gestion des CORS sur Laravel à l'aide d'un middleware personnalisé.

Qu'est-ce que les CORS ?

Les CORS (Cross-Origin Resource Sharing) sont un mécanisme qui permet à un serveur web d'indiquer les origines autorisées à accéder à ses ressources. Cette sécurité est essentielle pour protéger vos applications contre les accès non autorisés.

Implémentation du Middleware

Notre solution s'articule autour de deux fichiers principaux : le Kernel.php et un middleware personnalisé ContentSecurityPolicy.php.

1. Configuration du Kernel

Dans le fichier Kernel.php, nous déclarons notre middleware dans le groupe 'web' :

protected $middlewareGroups = [
    'web' => [
        // Autres middlewares...
        \App\Http\Middleware\ContentSecurityPolicy::class,
    ],
];

2. Le Middleware ContentSecurityPolicy

Le middleware ContentSecurityPolicy est le cœur de notre solution. Il définit les politiques de sécurité et les en-têtes CORS nécessaires.

Créez un fichier “ContentSecurityPolicy.php” dans votre dossier Middleware :

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;

class ContentSecurityPolicy
{
    public function handle(Request $request, Closure $next)
    {
        $response = $next($request);

        // Content Security Policy (CSP)
        $cspDirectives = [
            "default-src" => "'self'",
            "script-src" => "'self' 'unsafe-inline' 'unsafe-eval'",
            "style-src" => "'self' 'unsafe-inline'",
            "img-src" => "'self' data: https:",
            "font-src" => "'self' data:",
            "connect-src" => "'self'",
            "media-src" => "'self'",
            "object-src" => "'none'",
            "frame-src" => "'self'",
            "frame-ancestors" => "'self'",
            "base-uri" => "'self'",
            "form-action" => "'self'",
            "upgrade-insecure-requests" => null
        ];

        $cspHeader = implode('; ', array_map(
            function ($key, $value) {
                return $value === null ? $key : "$key $value";
            },
            array_keys($cspDirectives),
            $cspDirectives
        ));

        // Set security headers
        $response->headers->set('Content-Security-Policy', $cspHeader);
        $response->headers->set('X-Content-Type-Options', 'nosniff');
        $response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin');
        $response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');

        // Set Permissions-Policy header with commonly restricted features
        $response->headers->set('Permissions-Policy',
            'accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=(), interest-cohort=()'
        );

        $response->headers->remove('X-Powered-By');
        $response->headers->remove('server');

        return $response;
    }
}

Dans notre exemple, nous autorisons le script-src à “unsafe-eval” pour AlpineJS. Si vous souhaitez tout de fois être plus stricte et ne pas l’inclure, vous pouvez vous rendre ici pour une version d’AlpineJS plus stricte en matière d’eval: https://alpinejs.dev/advanced/csp

Bien entendu, ajoutez les domaines autorisés pour chacun des cas de votre application. Si vous souhaitez par exemple ajouter une iframe openstreetmap, modifiez vos CSP comme cela:

// Content Security Policy (CSP)
$cspDirectives = [
    // autres directives ...
    "frame-src" => "'self' https://www.openstreetmap.org/",
];