Daniele Irsuti - Frontend developer

CORS: sicuro di conoscerlo?

CORS significa cross-origin HTTP request e sta ad indicare una chiamata http effettuata da dominio-di-provenienza (es: www.dominio-di-provenienza.it) a dominio-di-destinazione (es: www.dominio-di-destinazione.it).

Il problema su cui probabilmente tutti ci siamo schiantati almeno una volta è probabilmente questo:

Access to XMLHttpRequest at 'www.dominio-di-destinazione.it' from origin 'www.dominio-di-provenienza.it' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.

Il motivo per cui incappiamo nel suddetto problema è che dominio-di-destinazione non ha abilitato l’accesso al dominio-di-provenienza.

La cosa che spesso manda in confusione sviluppatore backend e sviluppatore frontend sta nel mezzo: il browser.

Perché?

Il browser per ragioni di sicurezza limita le richieste CORS e si accerta che sito di destinazione sia al corrente che la richiesta del sito di provenienza sia consentita.

Fatta questa premessa (ampiamente documentata su MDN) vorrei mostrare un esempio molto semplice di chiamata CORS che non va a buon fine. Per rendere l’esempio di brutale immediatezza, mostrerò direttamente in console (sul dominio di questo blog) il codice per effettuare una chiamata Ajax costruita con Postman verso la pagina mdn che spiega proprio cos’è CORS.

Cors request con preflight

La parte migliore che sfugge ai più

Quando si effettua una richiesta CORS, come nel caso mostrato nella gif di prima, parte una chiamata con metodo OPTIONS. Questa chiamata viene detta CORS preflight.

Di seguito il flusso di una CORS request con preflight.

Flusso della CORS request con preflight

Quello che non molti sanno è che se la richiesta soddisfa determinati requisiti la CORS preflight non viene effettuata:

Flusso della simple request

Metodi permessi:

  • GET
  • HEAD
  • POST

Header permessi:

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type con uno dei seguenti valori:

    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain
  • DPR
  • Downlink
  • Save-Data
  • Viewport-Width
  • Width

Sarà vero? Provo!

Cors request simple request

Quando vado a visualizzare l’header non è presente alcun preflight. C’è la POST request passa diretta. Nessun metodo OPTIONS.

Access-Control-Allow-Origin

Come abbiamo scritto in precedenza, la richiesta partita è consentita solo se dominio-di-provenienza la consente, altrimenti restituirà errore.

Per essere consentita, il browser verifica che nell’header di risposta sia presente la chiave ”Access-Control-Allow-Origin” con valore “dominio-di-provenienza” o, come spesso avrete visto, ”*” (ossia da qualsiasi provenienza).

Quindi lato backend che faccio?

Non è raro trovare soluzioni raffazzonate come applicare negli header del dominio-di-destinazione:

Access-Control-Allow-Origin: *

Fino a quando si tratta di simple request può andare bene, ma come come comportarsi quando ad arrivare sono richieste con metodo OPTIONS?

L’ideale sarebbe intercettare tutte le richieste OPTIONS e ritornare una risposta contenente i seguenti header:

HTTP STATUS 200
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS,
Access-Control-Allow-Headers: Content-Type

Ma è un soluzione artigianale, generalmente i framework più popolari hanno delle configurazioni già built-in che facilitano lo sviluppatore nel compito, possibilmente scrivendo anche una sola riga di codice.

Considerazioni personali

Io credo che tutti, veramente tutti, debbano conoscere CORS, frontender e backender. Per questo vi suggerisco vivamente di leggere l’articolo presente su MDN molto più tecnico ed accurato.

Fonti e approfondimenti