Hvordan aktiveres CORS med HTTPOnly Cookie til at sikre token?

I denne artikel ser vi, hvordan du aktiverer CORS (Cross-Origin Resource Sharing) med HTTPOnly-cookie for at sikre vores adgangstokens.

I dag er backend-servere og frontend-klienter installeret på forskellige domæner. Derfor skal serveren aktivere CORS for at tillade klienter at kommunikere med serveren på browsere.

Servere implementerer også statsløs godkendelse for bedre skalerbarhed. Tokens gemmes og vedligeholdes på klientsiden, men ikke på serversiden som session. Af sikkerhedsmæssige årsager er det bedre at gemme tokens i HTTPOnly-cookies.

Indholdsfortegnelse

Hvorfor er Cross-Origin-anmodninger blokeret?

Lad os antage, at vores frontend-applikation blev implementeret på https://app.toadmin.dk.com. Et script indlæst i https://app.toadmin.dk.com kan kun anmode om ressourcer med samme oprindelse.

Hver gang vi forsøger at sende en krydsoprindelsesanmodning til et andet domæne https://api.toadmin.dk.com eller en anden port https://app.toadmin.dk.com:3000 eller en anden ordning http://app.toadmin.dk.com, cross-origin anmodning vil blive blokeret af browseren.

  AWS-certificering – Hvad er mulighederne, og hvordan bliver man certificeret?

Men hvorfor den samme anmodning, der er blokeret af browseren, sendes fra en hvilken som helst backend-server ved hjælp af curl request eller sendt ved hjælp af værktøjer som postbuddet uden CORS-problem. Det er faktisk for sikkerheden at beskytte brugere mod angreb som CSRF (Cross-Site Request Forgery).

Lad os tage et eksempel, hvis en bruger loggede på deres egen PayPal-konto i deres browser. Hvis vi kan sende en krydsoprindelsesanmodning til paypal.com fra et script, der er indlæst på et andet domæne, malicious.com uden nogen CORS-fejl/blokering, ligesom vi sender anmodningen om samme oprindelse.

Angribere kan nemt sende deres ondsindede side https://malicious.com/transfer-money-to-attacker-account-from-user-paypal-account ved at konvertere den til short-URL for at skjule den faktiske URL. Når brugeren klikker på et ondsindet link, vil scriptet, der er indlæst i domænet malicious.com, sende en krydsoprindelsesanmodning til PayPal om at overføre brugerbeløbet til hackerens PayPal-konto, der udføres. Alle brugere, der har logget ind på deres PayPal-konto og har klikket på dette ondsindede link, vil miste deres penge. Enhver kan nemt stjæle penge uden en PayPal-konto brugerkendskab.

Af ovenstående grund blokerer browsere alle anmodninger om krydsoprindelse.

Hvad er CORS (Cross-Origin Resource Sharing)?

CORS er en header-baseret sikkerhedsmekanisme, der bruges af serveren til at fortælle browseren at sende en krydsoprindelsesanmodning fra betroede domæner.
Serveren aktiveret med CORS-headere, der bruges til at undgå anmodninger om krydsoprindelse blokeret af browsere.

Hvordan virker CORS?

Da serveren allerede har defineret sit betroede domæne i sin CORS-konfiguration. Når vi sender en anmodning til serveren, vil svaret fortælle browseren, at det anmodede domæne er tillid til eller ej i dets header.

Der er to typer CORS-anmodninger:

  • Enkel anmodning
  • Preflight-anmodning

Enkel anmodning:

  • Browseren sender anmodningen til et cross-origin domæne med oprindelse (https://app.toadmin.dk.com).
  • Serveren sender det tilsvarende svar tilbage med tilladte metoder og tilladt oprindelse.
  • Efter at have modtaget anmodningen vil browseren kontrollere, at den sendte oprindelsesheaderværdi (https://app.toadmin.dk.com) og den modtagne adgangskontrol-allow-origin-værdi (https://app.toadmin.dk.com) er den samme eller jokertegn

. Ellers vil det give en CORS-fejl.

  • Preflight-anmodning:
  • Afhængigt af den tilpassede anmodningsparameter fra krydsoprindelsesanmodningen som metoder (PUT, DELETE) eller brugerdefinerede overskrifter eller anden indholdstype osv. Browseren vil beslutte at sende en forhåndskontrol OPTIONS-anmodning for at kontrollere, om den faktiske anmodning er sikker at sende eller ikke.

Efter at have modtaget svaret (statuskode: 204, hvilket betyder intet indhold), vil browseren søge efter adgangskontrol-allow-parametrene for den faktiske anmodning. Hvis anmodningsparametrene er tilladt af serveren. Den faktiske krydsoprindelsesanmodning, der er sendt og modtaget

  Sådan slår du to-faktor-godkendelse til for LinkedIn

Hvis access-control-allow-origin: *, så er svaret tilladt for alle oprindelser. Men det er ikke sikkert, medmindre du har brug for det.

Hvordan aktiverer man CORS?

For at aktivere CORS for ethvert domæne skal du aktivere CORS-headere for at tillade oprindelse, metoder, brugerdefinerede overskrifter, legitimationsoplysninger osv.

  • Browseren læser CORS-headeren fra serveren og tillader kun faktiske anmodninger fra klienten efter at have verificeret anmodningsparametrene.
  • Access-Control-Allow-Origin: For at angive nøjagtige domæner (https://app.geekflate.com, https://lab.toadmin.dk.com) eller jokertegn
  • Access-Control-Allow-Methods: At tillade HTTP-metoderne (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS), som kun vi har brug for.
  • Access-Control-Allow-Headers: For kun at tillade specifikke headere (autorisation, csrf-token)
  • Access-Control-Allow-Credentials: Boolesk værdi, der bruges til at tillade cross-origin-legitimationsoplysninger (cookies, autorisationshoved).

Access-Control-Max-Age: Beder browseren om at cache preflight-svaret i nogen tid.

Access-Control-Expose-Headers: Angiv overskrifter, der er tilgængelige via script på klientsiden.

Følg denne vejledning for at aktivere CORS i apache og Nginx-webserver.

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')
})

Aktivering af CORS i ExpressJS

Lad os tage et eksempel på en ExpressJS-app uden CORS:

npm install cors

I ovenstående eksempel har vi aktiveret brugernes API-endepunkt for POST, PUT, GET metoder, men ikke DELETE metoden.

For let at aktivere CORS i ExpressJS-appen kan du installere cors

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

Access-Control-Allow-Origin

app.use(cors({
    origin: 'https://app.toadmin.dk.com'
}));

Aktivering af CORS for alle domæner

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

Aktivering af CORS for et enkelt domæne

Hvis du vil tillade CORS for oprindelse https://app.toadmin.dk.com og https://lab.toadmin.dk.com

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

Access-Control-Allow-Methods

For at aktivere CORS for alle metoder skal du udelade denne mulighed i CORS-modulet i ExpressJS. Men for at aktivere specifikke 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

Bruges til at tillade andre overskrifter end standarder at sende med faktiske anmodninger.

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
}));

Adgangskontrol-Tillad-legitimationsoplysninger

Udelad dette, hvis du ikke vil fortælle browseren om at tillade legitimationsoplysninger på anmodning, selv på withCredentials er sat til sand.

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 
}));

Adgangskontrol-Max-Alder

For at tilskynde browseren til at cache preflight-svaroplysningerne i cachen i et bestemt sekund. Udelad dette, hvis du ikke vil cache 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 cachelagrede preflight-svar vil være tilgængeligt i 10 minutter i browseren.

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

  Køb gavekort med krypto ved hjælp af disse platforme [2022]

Hvis vi sætter jokertegnet

i exposedHeaders vil den ikke afsløre autorisationsoverskriften. Så vi er nødt til at afsløre eksplicit som nedenfor

Ovenstående vil også afsløre alle headere og autorisationsheader.

  • Hvad er en HTTP-cookie?
  • En cookie er et lille stykke data, som serveren sender til klientbrowseren. Ved senere anmodninger sender browseren alle cookies relateret til det samme domæne ved hver anmodning.
  • Cookie har sin egenskab, som kan defineres til at få en cookie til at fungere anderledes, som vi har brug for.
  • Navn Navnet på cookien.
  • værdi: data for cookie, der svarer til cookie-navn
  • Domæne: cookies sendes kun til det definerede domæne
  • Sti: cookies sendes kun efter den definerede URL-præfikssti. Antag, hvis vi har defineret vores cookie-sti som path=’admin/’. Cookies sendes ikke til URL’en https://toadmin.dk.com/expire/, men sendes med URL-præfiks https://toadmin.dk.com/admin/
  • Max-Age/Expires(antal i sekund): Hvornår skal cookien udløbe. En levetid af cookien gør cookien ugyldig efter den angivne tid. [Strict, Lax, None]HTTPOnly(Boolean): Backend-serveren kan få adgang til denne HTTPOnly-cookie, men ikke klientsidescriptet, når det er sandt. Sikker (boolesk): Cookies sendes kun over et SSL/TLS-domæne, når det er sandt.sameSite(streng

): Bruges til at aktivere/begrænse cookies, der sendes på tværs af websteder. For at få flere detaljer om cookies se sameSite

MDN

. Den accepterer tre muligheder Strict, Lax, None. Cookie sikker værdi sat til sand for cookie-konfigurationen sameSite=Ingen.

Hvorfor HTTPOnly-cookie til tokens?

Lagring af adgangstokenet, der sendes fra serveren, i lager på klientsiden som lokalt lager, indekseret DB og cookie (HTTTPonly ikke sat til sand) er mere sårbare over for XSS-angreb. Antag, at hvis en af ​​dine sider er svag til et XSS-angreb. Angribere kan misbruge brugertokens, der er gemt i browseren.

Kun HTTP-cookies sættes/hentes kun af server/backend, men ikke på klientsiden.

  • Client-side script begrænset til at få adgang til denne HTTP-only cookie. Så HTTPOnly cookies er ikke sårbare over for XSS-angreb og er mere sikre. Fordi det kun er tilgængeligt af serveren.
  • Aktiver HTTPOnly-cookie i CORS-aktiveret backend
  • Aktivering af Cookie i CORS kræver nedenstående konfiguration i applikationen/serveren.
  • Indstil Access-Control-Allow-Credentials header til sand.

Access-Control-Allow-Origin og Access-Control-Allow-Headers bør 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 attribut bør være None.

For at aktivere sameSite-værdien til ingen, skal du indstille den sikre værdi til sand: Aktiver backend med SSL/TLS-certifikat til at fungere i domænenavnet.

Lad os se et eksempel på en kode, der sætter et adgangstoken i HTTPOnly-cookien efter kontrol af loginoplysningerne.

Du kan konfigurere CORS- og HTTPOnly-cookies ved at implementere ovenstående fire trin i dit backend-sprog og webserver.

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

Du kan følge denne tutorial for apache og Nginx for at aktivere CORS ved at følge ovenstående trin.

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

med legitimationsoplysninger for anmodning om krydsoprindelse

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

Legitimationsoplysninger (cookie, autorisation) sendt med anmodningen med samme oprindelse som standard. For krydsoprindelse skal vi angive withCredentials til sand.

axios.defaults.withCredentials = true

XMLHttpRequest API

Hent API

JQuery AjaxAxiosKonklusion Jeg håber, at ovenstående artikel hjælper dig med at forstå, hvordan CORS fungerer og aktivere CORS for anmodninger om krydsoprindelse på serveren. Hvorfor lagring af cookies i HTTPOnly er sikkert, og hvordan med legitimationsoplysninger, der bruges i klienter til anmodninger om krydsoprindelse.