Skip to content

Configurazione CORS e Cookie per Chrome ​

Problema ​

Chrome non invia cookie nelle richieste AJAX cross-origin, mentre Firefox funziona.

Causa ​

Chrome applica politiche di sicurezza piΓΉ restrittive per i cookie di terze parti (third-party cookies) rispetto a Firefox. Per far funzionare credentials: "include", sono necessarie configurazioni specifiche sia lato server che lato client.

Soluzione ​

1. Lato Server PHP (Erp_auth.php o middleware CORS) ​

Il server deve inviare gli header CORS corretti:

php
// ❌ NON FUNZIONA con credentials
header('Access-Control-Allow-Origin: *');

// βœ… FUNZIONA: origin specifico
$allowed_origins = [
    'http://localhost:5173',  // dev
    'https://app.daisy.local', // prod
];

$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
if (in_array($origin, $allowed_origins)) {
    header("Access-Control-Allow-Origin: $origin");
}

// βœ… OBBLIGATORIO per credentials
header('Access-Control-Allow-Credentials: true');

// βœ… Metodi e header permessi
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Daisy-Erp');

// βœ… Gestione preflight OPTIONS
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(204);
    exit;
}

I cookie devono essere impostati con attributi specifici:

php
// ❌ NON FUNZIONA su Chrome cross-origin
setcookie('session_id', $value, [
    'path' => '/',
    'httponly' => true,
]);

// βœ… FUNZIONA su Chrome
setcookie('session_id', $value, [
    'path' => '/',
    'httponly' => true,
    'secure' => true,      // Richiede HTTPS
    'samesite' => 'None',  // Permette cross-origin
]);

⚠️ IMPORTANTE: Secure richiede HTTPS. Per sviluppo locale usa:

  • https://api.local.daisy (con certificato self-signed)
  • Oppure disabilita temporaneamente le restrizioni Chrome (non raccomandato per prod)

3. Lato Client (giΓ  configurato) ​

typescript
// app/lib/api.ts
const response = await fetch(`${baseUrl}${endpoint}`, {
    credentials: "include", // βœ… Include cookies
    headers: {
        "Content-Type": "application/json",
        "Daisy-Erp": "frontend",
    },
});

Verifica Configurazione ​

1. Controlla Headers di Risposta (Chrome DevTools) ​

Apri DevTools β†’ Network β†’ seleziona una richiesta API:

Response Headers:
βœ… Access-Control-Allow-Origin: http://localhost:5173
βœ… Access-Control-Allow-Credentials: true
❌ Access-Control-Allow-Origin: * (NON funziona)

Apri DevTools β†’ Application β†’ Cookies:

βœ… SameSite: None
βœ… Secure: true
❌ SameSite: Lax/Strict (non inviato cross-origin)

3. Test nel Console ​

javascript
fetch('https://api.local.daisy/erp/erp_auth/check-auth/', {
    credentials: 'include'
})
.then(r => r.json())
.then(console.log);

Se vedi i cookie nella tab "Cookies" della richiesta in Network, funziona! βœ…

Esempio Completo PHP ​

php
<?php
// cors.php - Middleware CORS centralizzato

class CorsMiddleware {
    private $allowed_origins = [
        'http://localhost:5173',
        'https://app.daisy.local',
    ];

    public function handle() {
        $origin = $_SERVER['HTTP_ORIGIN'] ?? '';

        if (in_array($origin, $this->allowed_origins)) {
            header("Access-Control-Allow-Origin: $origin");
            header('Access-Control-Allow-Credentials: true');
            header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
            header('Access-Control-Allow-Headers: Content-Type, Daisy-Erp');
        }

        // Preflight
        if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
            http_response_code(204);
            exit;
        }
    }

    public function setCookie($name, $value, $options = []) {
        $defaults = [
            'expires' => time() + 3600,
            'path' => '/',
            'httponly' => true,
            'secure' => true,    // βœ… HTTPS required
            'samesite' => 'None', // βœ… Cross-origin
        ];

        setcookie($name, $value, array_merge($defaults, $options));
    }
}

// In Erp_auth.php
$cors = new CorsMiddleware();
$cors->handle();

// Quando imposti il cookie di sessione
$cors->setCookie('session_id', $session_id);

Troubleshooting ​

  1. Verifica che sia HTTPS: Secure richiede HTTPS, HTTP non funziona
  2. Cancella cache e cookie: Settings β†’ Privacy β†’ Clear browsing data
  3. Disabilita estensioni: Alcune estensioni bloccano third-party cookies
  4. Controlla flag Chrome: chrome://flags/#same-site-by-default-cookies

Firefox funziona, Safari no ​

Safari ha restrizioni ancora piΓΉ severe. Assicurati che:

  • Origin sia nella lista allowed_origins
  • Cookie abbiano SameSite=None; Secure
  • Server invii Access-Control-Allow-Credentials: true

Errore "Blocked by CORS policy" ​

Controlla che:

  • Access-Control-Allow-Origin sia l'origin specifico (non *)
  • Access-Control-Allow-Credentials: true sia presente
  • Server gestisca preflight OPTIONS correttamente

Riferimenti ​

Documentazione Elerama Frontend