Waarom cookie-beveiliging belangrijk is
Cookies zijn het primaire mechanisme voor sessiebeheer op het web. Een sessiecookie die in verkeerde handen valt, geeft een aanvaller directe toegang tot het account van het slachtoffer — zonder wachtwoord, zonder MFA. Cookie-beveiliging is daarom een fundamenteel onderdeel van elke webapplicatie.
De vier essentiële cookie-attributen
1. HttpOnly
Set-Cookie: session=abc123; HttpOnly
Wat het doet: voorkomt dat JavaScript de cookie kan lezen via document.cookie.
Bescherming tegen: XSS-gebaseerde sessiediefstal. Zelfs als een aanvaller JavaScript kan injecteren, kan het sessiecookie niet worden geëxfiltreerd.
Wanneer gebruiken: altijd voor sessiecookies en authenticatietokens. Laat dit attribuut alleen weg als JavaScript de cookie daadwerkelijk moet lezen (bijv. een voorkeurscookie voor taal of thema).
2. Secure
Set-Cookie: session=abc123; Secure
Wat het doet: de cookie wordt alleen verzonden over HTTPS-verbindingen.
Bescherming tegen: man-in-the-middle aanvallen op onbeveiligde verbindingen. Zonder dit attribuut kan een aanvaller op hetzelfde netwerk (bijv. openbaar WiFi) het cookie onderscheppen.
Wanneer gebruiken: altijd in productie. In ontwikkeling (localhost) kan het worden weggelaten, maar zorg dat uw code het automatisch instelt op basis van de omgeving.
3. SameSite
Set-Cookie: session=abc123; SameSite=Strict
Wat het doet: bepaalt of de cookie wordt meegezonden bij cross-site requests.
| Waarde | Gedrag |
|---|---|
| Strict | Cookie wordt nooit meegezonden bij cross-site requests |
| Lax | Cookie wordt meegezonden bij top-level navigatie (links) maar niet bij POST/iframe/AJAX |
| None | Cookie wordt altijd meegezonden (vereist Secure attribuut) |
Bescherming tegen: Cross-Site Request Forgery (CSRF). Met Strict of Lax kan een kwaadaardige website geen acties uitvoeren namens de ingelogde gebruiker.
Aanbeveling: Strict voor sessiecookies. Lax als u inkomende links vanaf andere sites moet ondersteunen met behoud van sessie. None alleen als u cross-site embedding nodig heeft (bijv. betaalwidgets in iframes).
4. Path en Domain
Set-Cookie: session=abc123; Path=/; Domain=example.nl
| Attribuut | Aanbeveling |
|---|---|
| Path | Zo specifiek mogelijk. / voor sessiecookies, /api voor API-tokens |
| Domain | Laat leeg (standaard: exact het huidige domein) tenzij u subdomeinen moet ondersteunen |
Volledige veilige cookie-configuratie
Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=86400
Implementatievoorbeelden
Express.js (Node.js):
app.use(session({
cookie: {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict',
maxAge: 24 * 60 * 60 * 1000, // 24 uur
path: '/',
},
// ... overige sessieconfiguratie
}));
Next.js (API route):
import { cookies } from 'next/headers';
cookies().set('session', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict',
maxAge: 86400,
path: '/',
});
Django (Python):
# settings.py
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE = 'Strict'
SESSION_COOKIE_AGE = 86400
CSRF_COOKIE_HTTPONLY = True
CSRF_COOKIE_SECURE = True
Cookie-prefixen
Moderne browsers ondersteunen cookie-prefixen die extra beperkingen afdwingen:
| Prefix | Vereisten |
|---|---|
| __Secure- | Cookie moet Secure attribuut hebben en via HTTPS zijn gezet |
| __Host- | Cookie moet Secure hebben, geen Domain, en Path=/ |
Set-Cookie: __Host-session=abc123; Secure; HttpOnly; SameSite=Strict; Path=/
__Host- is de strengste optie en voorkomt dat het cookie per ongeluk beschikbaar wordt op subdomeinen.
Sessiebeveiliging
Naast cookie-attributen zijn er aanvullende maatregelen voor sessiebeheer:
Sessiefixatie voorkomen
Genereer na succesvolle authenticatie altijd een nieuw sessie-ID:
// Na succesvolle login
req.session.regenerate((err) => {
req.session.userId = user.id;
// Gebruik het nieuwe sessie-ID
});
Sessie-timeout
Stel twee types timeout in:
| Type | Aanbeveling | Voorbeeld | |---|---|---| | Inactiviteitstimeout | 15-30 minuten voor gevoelige applicaties | Bankingapp: 15 min | | Absolute timeout | 8-24 uur maximum sessielevensduur | SaaS-app: 24 uur |
Token-rotatie
Vernieuw sessietokens periodiek zonder de gebruiker uit te loggen:
// Elke 15 minuten een nieuw token
if (session.lastRotation < Date.now() - 15 * 60 * 1000) {
session.regenerate();
session.lastRotation = Date.now();
}
Third-party cookies: het einde
Browsers beperken steeds meer de functionaliteit van third-party cookies:
| Browser | Status third-party cookies | |---|---| | Safari | Geblokkeerd sinds 2020 (ITP) | | Firefox | Geblokkeerd (Enhanced Tracking Protection) | | Chrome | Geleidelijke beperking via Privacy Sandbox |
Impact: als u afhankelijk bent van third-party cookies voor tracking, analytics of authenticatie, bereid u dan voor op alternatieven:
- First-party tracking
- Server-side analytics
- OAuth/OIDC voor cross-domain authenticatie
Veelgemaakte fouten
| Fout | Risico | |---|---| | Sessiecookie zonder HttpOnly | XSS leidt tot sessiediefstal | | Secure ontbreekt in productie | Cookie zichtbaar op HTTP | | SameSite niet ingesteld | CSRF-kwetsbaarheid | | Te lange sessie-levensduur | Vergroot exploitatievenster | | Geen sessie-regeneratie na login | Sessiefixatie-aanval mogelijk | | Gevoelige data in cookie-waarde | Cookie-inhoud is leesbaar en manipuleerbaar | | JWT in localStorage | Toegankelijk via XSS (gebruik HttpOnly cookie) |
Cookie-audit checklist
- [ ] Alle sessiecookies hebben HttpOnly
- [ ] Alle cookies in productie hebben Secure
- [ ] SameSite is ingesteld op Strict of Lax
- [ ] Cookie-levensduur is beperkt (geen permanente sessies)
- [ ] Sessie-ID wordt geregenereerd na login
- [ ] Geen gevoelige data in cookie-waarden opgeslagen
- [ ] Cookie-prefixen gebruikt waar mogelijk
- [ ] Third-party cookie afhankelijkheden in kaart gebracht
Scan uw website gratis met WarDek — OWASP, NIS2, AVG, AI Act compliance in één scan.