Introduction à CORS

Julien Tanguy, Sounderbox

Introduction à CORS

Cross-Origin Resource Sharing

Pourquoi ?

Partager des ressources entre différents domaines

Content Security Policies

Si on modifie document.domain, il faut le faire sur toutes les pages (sub.example.com et example.com)

CORS

#NoCORS

Requêtes CORS simples

Exemple JS

fetch(`https://example.com/resource`, {
    method: 'GET',
    headers: { 'Accept': 'application/json' },
}).then(res => {
    if (res.ok) {
        return res.json()
    } else {
        return Promise.reject(res.statusText)
    }
}).then(console.log)
.catch(console.error)

Preflight

Requêtes nécessitant un preflight

Tout ce qui n’est pas une requête simple

Exemple JS

fetch(`https://example.com/resource`, {
    method: 'POST',
    headers: { 'Accept': 'application/json',
               'Content-Type': 'application/json' },
    body: { id: '9408e0e9-9dcc-46a1-a75b-be553e39da15' }
}).then(res => {
    if (res.ok) {
        return res.json()
    } else {
        return Promise.reject(res.statusText)
    }
}).then(console.log)
.catch(console.error)

Requête preflight

OPTIONS /resource HTTP/1.1
Host: example.com
User-Agent: 
Accept: 
Connection: 
Origin: https://my.domain.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type

Réponse preflight

HTTP/1.1 200 OK
Date: 
Server: 
Access-Control-Allow-Origin: https://my.domain.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400
Content-Encoding: 
Content-Length: 
Keep-Alive: 
Connection: 
Content-Type: 

Requête

POST /resource HTTP/1.1
Host: example.com
User-Agent: 
Accept: 
Content-Type: application/json
Referer: 
Content-Length: 
Origin: https://my.domain.com

{ "id": "9408e0e9-9dcc-46a1-a75b-be553e39da15" }

Réponse

HTTP/1.1 200 OK
Date: 
Server: 
Access-Control-Allow-Origin: https://my.domain.com
Content-Encoding: ..
Content-Length: 
Keep-Alive: 
Connection: 
Content-Type: 

Credentials

Credentials ?

Exemple de mauvaise config:

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

Exemple JS

fetch(`https://example.com/resource`, {
    method: 'GET',
    credentials: 'include',
    headers: { 'Accept': 'application/json' },
}).then(res => {
    if (res.ok) {
        return res.json()
    } else {
        return Promise.reject(res.statusText)
    }
}).then(console.log)
.catch(console.error)

Requête

GET /resource HTTP/1.1
Host: example.com
User-Agent: ..
Accept: ..
Origin: http://my.domain.com
Cookie: session_id=2

Réponse

HTTP/1.1 200 OK
Date: 
Server: 
Access-Control-Allow-Origin: http://my.domain.com
Access-Control-Allow-Credentials: true
Set-Cookie: session_id=2; expires=...
Content-Encoding: 
Content-Length: 
Content-Type: 

Récap

Côté serveur

Liens

Fork me on Github