Hvordan aktivere CORS med HTTPOnly Cookie for å sikre token?

I denne artikkelen ser vi hvordan du aktiverer CORS (Cross-Origin Resource Sharing) med HTTPOnly-informasjonskapsel for å sikre tilgangstokenene våre.

I dag er backend-servere og frontend-klienter distribuert på forskjellige domener. Derfor må serveren aktivere CORS for å tillate klienter å kommunisere med serveren på nettlesere.

Servere implementerer også statsløs autentisering for bedre skalerbarhet. Tokens lagres og vedlikeholdes på klientsiden, men ikke på serversiden som en økt. Av sikkerhetshensyn er det bedre å lagre tokens i HTTPOnly-informasjonskapsler.

Innholdsfortegnelse

Hvorfor blokkeres Cross-Origin-forespørsler?

La oss anta at frontend-applikasjonen vår ble distribuert på https://app.tipsbilk.net.com. Et skript lastet inn i https://app.tipsbilk.net.com kan bare be om ressurser med samme opprinnelse.

Hver gang vi prøver å sende en kryssopprinnelsesforespørsel til et annet domene https://api.tipsbilk.net.com eller en annen port https://app.tipsbilk.net.com:3000 eller en annen ordning http://app.tipsbilk.net.com, cross-origin-forespørsel vil bli blokkert av nettleseren.

Men hvorfor den samme forespørselen blokkert av nettleseren sendes fra en hvilken som helst backend-server ved å bruke curl-forespørsel eller sendes ved å bruke verktøy som postmannen uten CORS-problem. Det er faktisk for sikkerhet å beskytte brukere mot angrep som CSRF (Cross-Site Request Forgery).

  Hvordan få to telefoner til å ringe hverandre

La oss ta et eksempel, anta at hvis noen bruker logget på sin egen PayPal-konto i nettleseren. Hvis vi kan sende en kryssopprinnelsesforespørsel til paypal.com fra et skript lastet på et annet domene malicious.com uten CORS-feil/blokkering, som om vi sender samme opprinnelsesforespørsel.

Angripere kan enkelt sende sin ondsinnede side https://malicious.com/transfer-money-to-attacker-account-from-user-paypal-account ved å konvertere den til en kort URL for å skjule den faktiske nettadressen. Når brukeren klikker på en ondsinnet lenke, vil skriptet som er lastet inn i domenet malicious.com sende en kryssopprinnelsesforespørsel til PayPal om å overføre brukerbeløpet til angriperens PayPal-konto som vil bli utført. Alle brukere som har logget på PayPal-kontoen sin og klikket på denne ondsinnede koblingen, vil miste pengene sine. Hvem som helst kan enkelt stjele penger uten en PayPal-konto brukerkunnskap.

Av grunnen ovenfor blokkerer nettlesere alle forespørsler om kryssopprinnelse.

Hva er CORS (Cross-Origin Resource Sharing)?

CORS er en hodebasert sikkerhetsmekanisme som brukes av serveren for å fortelle nettleseren å sende en kryssopprinnelsesforespørsel fra klarerte domener.
Serveren er aktivert med CORS-hoder som brukes for å unngå forespørsler med kryssopprinnelse blokkert av nettlesere.

Hvordan fungerer CORS?

Siden serveren allerede har definert sitt klarerte domene i CORS-konfigurasjonen. Når vi sender en forespørsel til serveren, vil svaret fortelle nettleseren at det forespurte domenet er klarert eller ikke i overskriften.

To typer CORS-forespørsler er der:

  • Enkel forespørsel
  • Preflight-forespørsel

Enkel forespørsel:

  • Nettleseren sender forespørselen til et kryssopprinnelsesdomene med opprinnelse (https://app.tipsbilk.net.com).
  • Serveren sender tilbake det tilsvarende svaret med tillatte metoder og tillatt opprinnelse.
  • Etter å ha mottatt forespørselen, vil nettleseren sjekke at den sendte opprinnelseshodeverdien (https://app.tipsbilk.net.com) og den mottatte access-control-allow-origin-verdien (https://app.tipsbilk.net.com) er de samme eller jokertegn

. Ellers vil det gi en CORS-feil.

  • Preflight-forespørsel:
  • Avhengig av den tilpassede forespørselsparameteren fra kryssopprinnelsesforespørselen, som metoder (PUT, DELETE) eller egendefinerte overskrifter eller annen innholdstype osv. Nettleseren vil bestemme seg for å sende en forhåndskontroll OPTIONS-forespørsel for å sjekke om den faktiske forespørselen er trygg å sende eller ikke.

Etter å ha mottatt svaret (statuskode: 204, som betyr ikke noe innhold), vil nettleseren se etter parametrene for tilgangskontroll-tillat for den faktiske forespørselen. Hvis forespørselsparametrene er tillatt av serveren. Selve kryssopprinnelsesforespørselen sendt og mottatt

  Trenger du Anti-Ransomware-programvare til PC-en din?

Hvis access-control-allow-origin: *, er svaret tillatt for alle opprinnelser. Men det er ikke trygt med mindre du trenger det.

Hvordan aktivere CORS?

For å aktivere CORS for et hvilket som helst domene, aktiver CORS-overskrifter for å tillate opprinnelse, metoder, tilpassede overskrifter, legitimasjon osv.

  • Nettleseren leser CORS-overskriften fra serveren og tillater faktiske forespørsler fra klienten bare etter å ha verifisert forespørselsparametere.
  • Access-Control-Allow-Origin: For å spesifisere eksakte domener (https://app.geekflate.com, https://lab.tipsbilk.net.com) eller jokertegn
  • Access-Control-Allow-Methods: Å tillate HTTP-metodene (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS) som bare vi trenger.
  • Access-Control-Allow-Headers: For å tillate bare spesifikke overskrifter (autorisasjon, csrf-token)
  • Access-Control-Allow-Credentials: Boolsk verdi som brukes for å tillate cross-origin-legitimasjon (informasjonskapsler, autorisasjonsoverskrift).

Access-Control-Max-Age: Ber nettleseren om å bufre preflight-svaret i en stund.

Access-Control-Expose-Headers: Spesifiser overskrifter som er tilgjengelige med skript på klientsiden.

For å aktivere CORS i apache og Nginx webserver, følg denne veiledningen.

const express = require('express');
const app = express()

app.get('/users', function (req, res, next) {
  res.json({msg: 'user get'})
});

app.post('/users', function (req, res, next) {
    res.json({msg: 'user create'})
});

app.put('/users', function (req, res, next) {
    res.json({msg: 'User update'})
});

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

Aktiverer CORS i ExpressJS

La oss ta et eksempel på en ExpressJS-app uten CORS:

npm install cors

I eksemplet ovenfor har vi aktivert brukernes API-endepunkt for POST-, PUT-, GET-metodene, men ikke DELETE-metoden.

For enkelt å aktivere CORS i ExpressJS-appen, kan du installere cors

app.use(cors({
    origin: '*'
}));

Access-Control-Allow-Origin

app.use(cors({
    origin: 'https://app.tipsbilk.net.com'
}));

Aktiverer CORS for alle domener

app.use(cors({
    origin: [
        'https://app.geekflare.com',
        'https://lab.geekflare.com'
    ]
}));

Aktivering av CORS for et enkelt domene

Hvis du vil tillate CORS for opprinnelse https://app.tipsbilk.net.com og https://lab.tipsbilk.net.com

app.use(cors({
    origin: [
        'https://app.geekflare.com',
        'https://lab.geekflare.com'
    ],
    methods: ['GET', 'PUT', 'POST']
}));

Tilgangskontroll-Tillat-metoder

For å aktivere CORS for alle metoder, utelat dette alternativet i CORS-modulen i ExpressJS. Men for å aktivere spesifikke metoder (GET, POST, PUT).

app.use(cors({
    origin: [
        'https://app.geekflare.com',
        'https://lab.geekflare.com'
    ],
    methods: ['GET', 'PUT', 'POST'],
    allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token']
}));

Access-Control-Allow-Headers

Brukes for å tillate andre overskrifter enn standarder å sende med faktiske forespørsler.

app.use(cors({
    origin: [
        'https://app.geekflare.com',
        'https://lab.geekflare.com'
    ],
    methods: ['GET', 'PUT', 'POST'],
    allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'],
    credentials: true
}));

Access-Control-Tillat-legitimasjon

Utelat dette hvis du ikke vil fortelle nettleseren å tillate legitimasjon på forespørsel, selv på withCredentials er satt til true.

app.use(cors({
    origin: [
        'https://app.geekflare.com',
        'https://lab.geekflare.com'
    ],
    methods: ['GET', 'PUT', 'POST'],
    allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'],
    credentials: true,
    maxAge: 600 
}));

Access-Control-Max-Age

For å oppmuntre nettleseren til å bufre forhåndskontrollinformasjonen i hurtigbufferen i et spesifisert sekund. Utelat dette hvis du ikke vil bufre svaret.

app.use(cors({
    origin: [
        'https://app.geekflare.com',
        'https://lab.geekflare.com'
    ],
    methods: ['GET', 'PUT', 'POST'],
    allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'],
    credentials: true,
    maxAge: 600,
    exposedHeaders: ['Content-Range', 'X-Content-Range']
}));

Det bufrede forhåndskontrollsvaret vil være tilgjengelig i 10 minutter i nettleseren.

app.use(cors({
    origin: [
        'https://app.geekflare.com',
        'https://lab.geekflare.com'
    ],
    methods: ['GET', 'PUT', 'POST'],
    allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'],
    credentials: true,
    maxAge: 600,
    exposedHeaders: ['*', 'Authorization', ]
}));

Access-Control-Expose-Headers

  Hvordan fikse aldersbegrensning i Tinder

Hvis vi setter jokertegnet

i exposedHeaders vil den ikke vise autorisasjonsoverskriften. Så vi må avsløre eksplisitt som nedenfor

Ovennevnte vil også avsløre alle overskrifter og autorisasjonsoverskrifter.

  • Hva er en HTTP-informasjonskapsel?
  • En informasjonskapsel er et lite stykke data som serveren sender til klientnettleseren. Ved senere forespørsler vil nettleseren sende alle informasjonskapslene relatert til samme domene på hver forespørsel.
  • Informasjonskapsel har sitt attributt, som kan defineres for å få en informasjonskapsel til å fungere annerledes etter behov.
  • Navn Navn på informasjonskapselen.
  • verdi: data for informasjonskapselen som er relatert til informasjonskapselnavnet
  • Domene: informasjonskapsler sendes kun til det definerte domenet
  • Bane: informasjonskapsler sendes bare etter den definerte URL-prefiksbanen. Anta at hvis vi har definert informasjonskapselbanen vår som path=’admin/». Informasjonskapsler sendes ikke for URL-en https://tipsbilk.net.com/expire/, men sendes med URL-prefiks https://tipsbilk.net.com/admin/
  • Maks-alder/utløper (tall i sekund): Når bør informasjonskapselen utløpe. En levetid på informasjonskapselen gjør informasjonskapselen ugyldig etter den angitte tiden. [Strict, Lax, None]HTTPOnly(Boolean): Backend-serveren kan få tilgang til den HTTPOnly-informasjonskapselen, men ikke klientsideskriptet når sant. Sikkert (boolsk): Informasjonskapsler sendes bare over et SSL/TLS-domene når sant.sameSite(streng

): Brukes til å aktivere/begrense informasjonskapsler som sendes over forespørsler på tvers av nettsteder. For å vite mer om informasjonskapsler se sameSite

MDN

. Den godtar tre alternativer Strict, Lax, None. Sikker verdi for informasjonskapsler satt til sann for informasjonskapselkonfigurasjonen sameSite=Ingen.

Hvorfor HTTPOnly-informasjonskapsel for tokens?

Lagring av tilgangstoken som sendes fra serveren i lagring på klientsiden, som lokal lagring, indeksert DB og informasjonskapsel (HTTTPonly ikke satt til true) er mer sårbart for XSS-angrep. Anta at hvis noen av sidene dine er svake for et XSS-angrep. Angripere kan misbruke brukertokens som er lagret i nettleseren.

Bare HTTP-informasjonskapsler settes/hentes kun av server/backend, men ikke på klientsiden.

  • Skript på klientsiden begrenset til å få tilgang til den kun HTTP-informasjonskapselen. Så HTTPOnly-informasjonskapsler er ikke sårbare for XSS-angrep og er sikrere. Fordi det kun er tilgjengelig av serveren.
  • Aktiver HTTPOnly-informasjonskapsel i CORS-aktivert backend
  • Aktivering av informasjonskapsel i CORS krever konfigurasjonen nedenfor i applikasjonen/serveren.
  • Sett Access-Control-Allow-Credentials-overskriften til sann.

Access-Control-Allow-Origin og Access-Control-Allow-Headers skal ikke være et jokertegn

const express = require('express'); 
const app = express();
const cors = require('cors');

app.use(cors({ 
  origin: [ 
    'https://app.geekflare.com', 
    'https://lab.geekflare.com' 
  ], 
  methods: ['GET', 'PUT', 'POST'], 
  allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'], 
  credentials: true, 
  maxAge: 600, 
  exposedHeaders: ['*', 'Authorization' ] 
}));

app.post('/login', function (req, res, next) { 
  res.cookie('access_token', access_token, {
    expires: new Date(Date.now() + (3600 * 1000 * 24 * 180 * 1)), //second min hour days year
    secure: true, // set to true if your using https or samesite is none
    httpOnly: true, // backend only
    sameSite: 'none' // set to none for cross-request
  });

  res.json({ msg: 'Login Successfully', access_token });
});

app.listen(80, function () { 
  console.log('CORS-enabled web server listening on port 80') 
}); 

.

Cookie sameSite-attributtet skal være None.

For å aktivere sameSite-verdien til ingen, sett den sikre verdien til true: Aktiver backend med SSL/TLS-sertifikat for å fungere i domenenavnet.

La oss se en eksempelkode som setter et tilgangstoken i HTTPOnly-informasjonskapselen etter å ha sjekket påloggingsinformasjonen.

Du kan konfigurere CORS og HTTPOnly informasjonskapsler ved å implementere de fire trinnene ovenfor i ditt backend-språk og webserver.

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://api.tipsbilk.net.com/user', true);
xhr.withCredentials = true;
xhr.send(null);

Du kan følge denne opplæringen for apache og Nginx for å aktivere CORS ved å følge trinnene ovenfor.

fetch('http://api.tipsbilk.net.com/user', {
  credentials: 'include'
});

med påloggingsinformasjon for Cross-Origin-forespørsel

$.ajax({
   url: 'http://api.tipsbilk.net.com/user',
   xhrFields: {
      withCredentials: true
   }
});

Påloggingsinformasjon (informasjonskapsel, autorisasjon) sendt med samme opprinnelsesforespørsel som standard. For kryssopprinnelse må vi spesifisere withCredentials til true.

axios.defaults.withCredentials = true

XMLHttpRequest API

Hent API

JQuery AjaxAxiosKonklusjon Jeg håper artikkelen ovenfor hjelper deg å forstå hvordan CORS fungerer og aktiverer CORS for forespørsler om kryssopprinnelse på serveren. Hvorfor lagring av informasjonskapsler i HTTPOnly er sikkert og hvordan med påloggingsinformasjon som brukes i klienter for forespørsler med kryssopprinnelse.