Innføring i CORS

Innføring i CORS

I denne artikkelen får du et overblikk i problematikken rundt Cross-Origin Resource-Sharing (CORS), hvordan du konfigurerer node.js-servere til å støtte CORS og hvordan du får programmatisk tilgang til API-er som ikke støtter CORS.

Krysskilderestriksjoner

Hvis du har jobbet med API-er i nevneverdig grad har du garantert støtt på krysskilderestriksjoner, eller Cross Origin Resource Sharing (CORS).

CORS ble konstruert i 2004 som et alternativ til JSON with padding (JSONP), og er en grunnleggende metode for sikring av tilgangskontroll til våre APIer over det åpne nettet. JSONP er en utvidelse av JavaScript Object Notation (JSON) som ble utviklet for å dele data mellom nettsider tvers over adresse.

Nettlesere anser det som en sikkerhetstrussel om for eksempel foo.no uten videre deler data med bar.no og vice versa. Dette er en retningslinje som sier at et skript på foo.no ikke skal kunne få tilgang til data på eksempelvis bar.no (kalt same-origin policy).

Enkle spørringer (GET, POST, HEAD)

I det enkleste scenarioet starter krysskildekommunikasjon med at en klient gjør en GET-, POST- eller en HEAD-spørring mot en ressurs på en server. Spørringen inkluderer en Origin header som indikerer hvem som ber om tilgang. Serveren vil vurdere spørringens Origin og enten tillate eller nekte tilgang til ressursen.

Hvis serveren godtar spørringen så vil den leverer fra seg den etterspurte ressursen og en Access-Control-Allow-Origin header i responsen. Hvis denne matcher spørringens Origin, så vil nettleseren godta spørringen. Hvis denne mangler eller ikke matcher spørringens Origin så vil nettleseren nekte tilgang til ressursen. Hvis serveren ikke sender med en Access-Control-Allow-Origin vil nettleseren også nekte deg tilgang til ressursen.

Eksempel på en GET request

La oss si du fra din app ønsker tilgang til foo.client.no og sender følgende spørring mot bar.server.no:

Serveren sjekker Origin headeren, som sier at spørringen kommer fra foo.client.no. Hvis serveren godkjenner denne klienten sender den en respons tilbake som kan se slik ut:

Access-Control-Allow-Origin er i dette eksempelet satt til foo.client.no, hvilket betyr at det er bare denne adressen som har tilgang til ressursen. Serveren kan også sette  Access-Control-Allow-Origin til ”*”, hvilket betyr at alle klienter har tilgang, men dette anses som usikkert og bør ikke benyttes av andre API-er enn de som er helt åpne og som forventes brukt av alle typer klienter.

Komplekse spørringer

Dersom du sender spørringer med andre HTTP verb enn GET, POST og HEAD, samt POST-spørringer som inneholder andre innholdstyper enn application/x-www-form-urlencoded, multipart/form-data, eller text/plain så sendes det en såkalt preflight-spørring på forhånd for å forsikre at det er trygt å sende den faktiske spørringen. 

Denne preflight-spørringen sendes da som en OPTIONS-spørring med HTTP-verbet i en Access-Control-Request-Method-header.

Dersom du for eksempel ber om å gjøre en PUT eller DELETE mot en ressurs, vil serveren sjekke om dette er tilatt og sende tilbake tillatte metoder i Access-Control-Allow-Methods i tillegg til Access-Control-Allow-Origin.

Dersom spørringen godtas, får du OK på OPTIONS og på selve spørringen, men dersom den nektes vil du få nektet OPTIONS-spørringen og den faktiske PUT/DELETE-spørringen vil ikke bli sendt.

Express-server med CORS

Med node.js og Express er det det enkelt å lage en HTTP-server med støtte for CORS. Nedenfor ser du eksempel på server som støtter spørringer fra http://www.foo.no og som svarer på POST og DELETE (men uten å faktisk gjøre noe med spørringen).

Forbigå CORS for servere som ikke er satt opp med Access-Control-Allow-Origin

Ettersom støtte for CORS er valgbart i HTTP-protokollen, vil det nok hende at du støter på problemer når du lager apper som som vil bruke ressurser på servere som ikke har konfigurert en Access-Control-Allow-Origin-policy.

Du har i dette tilfellet to valg:

  1. Du kan kontakte server-administrator og be om at det konfigureres en Access-Control-Allow-Origin som gir din app tilgang.
  2. Du forbigår CORS ved å kjøre spørringene fra localhost. Dette krever at du har tilgang på en server.

For å vise til et praktisk eksempel, la oss anta du vil hente ut meteorologiske data fra api.met.no med følgende spørring: https://api.met.no/weatherapi/locationforecast/1.9/?lat=60.10;lon=9.58;msl=70.

Dette API-et er satt opp uten Access-Control-Allow-Origin og vil derfor bare svare på spørringer via nettleseren eller dersom du sender spørringen fra localhost med et verktøy som curl, men dersom du prøver å kjøre den gjennom XHR eller fetch vil du bli nektet med følgende melding (dersom du bruker Fetch):

Fetch API cannot load http://api.met.no/weatherapi/locationforecast/1.9/?lat=60.10;lon=9.58;msl=70. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://www.met.no' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled. 

Siden vi ofte vil ha resultater raskt, eliminerer vi valg 1 fra listen og går for valg 2: forbigår CORS ved å kjøre spørringen fra localhost. Dette gjør vi ved å ta i bruk en node-server med express og biblioteket curlrequest. Her er eksempel-appen vi vil bygge: https://bit.ly/apimetno

Denne lille applikasjonen tar i mot høyde- og breddegrader og henter data fra api.met.no uten det minste problem, selv om API-et altså egentlig ikke har støtte for CORS. Denne metoden kan du gjenbruke til alle API-er som ikke støtter krysskilde-spørringer men som er åpne for spørringer via localhost.

 

Om bloggeren:
Frontendutvikler med sans for JavaScript. Glad i å snakke om programmering, og har utgitt boken ReactJS Blueprints på Packt forlag.

comments powered by Disqus