synops/docs/erfaringer/multi_subdomain.md
vegard dfcec6b3b0 Kontekst-velger: Hjem og Administrasjon som separate lenker
Dropdown viser begge arbeidsflater med absolutte URLer
(ws.synops.no og adm.synops.no). Navigasjon mellom subdomener
fungerer uten å miste sesjon.

Erfaringsnotat: multi-subdomain med SvelteKit — ORIGIN-fellen,
cookie-domene, CSRF, OIDC redirect URIs, sjekkliste for nye
subdomener.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 02:30:41 +00:00

4.2 KiB

Erfaring: Multi-subdomain med SvelteKit (mars 2026)

Kontekst

Innføring av adm.synops.no som admin-domene ved siden av ws.synops.no (app) avslørte flere arkitekturelle blindsoner.

Problemer vi møtte

1. ORIGIN låser hostname

Symptom: event.url.hostname returnerte alltid ws.synops.no uansett hvilken Host-header som kom inn.

Årsak: ORIGIN=https://ws.synops.no i .env. SvelteKit adapter-node bruker ORIGIN for å konstruere event.url — den overskriver Host-headeren.

Løsning: Fjern ORIGIN. AUTH_TRUST_HOST=true lar SvelteKit lese hostname fra selve HTTP Host-headeren.

Læring: ORIGIN er ment for single-origin deployments. Multi-subdomain krever at SvelteKit leser Host dynamisk.

Symptom: Login på ws.synops.no ga ikke tilgang til adm.synops.no. Brukeren ble bedt om å logge inn igjen.

Årsak: Session-cookie var satt med domain=ws.synops.no (default). Cookien var ikke tilgjengelig for adm.synops.no.

Løsning: Sett cookie-domene til .synops.no i auth.ts. Alle subdomener deler sesjonen.

Læring: Wildcard cookie-domene (.synops.no) er nødvendig når flere subdomener trenger samme autentisering. Det er trygt så lenge alle subdomener er under vår kontroll.

3. CSRF cross-origin blokkering

Symptom: Cross-site POST form submissions are forbidden ved login-callback fra Authentik.

Årsak: SvelteKit sin innebygde CSRF-sjekk sammenligner request origin mot ORIGIN-variabelen. POST fra adm.synops.no til OIDC-callback ble blokkert.

Løsning: csrf: { checkOrigin: false } i svelte.config.js. Trygt fordi OIDC bruker PKCE + state som CSRF-beskyttelse.

Læring: SvelteKit sin CSRF-sjekk er for streng for multi-origin. Deaktiver den når du har egen CSRF-mekanisme.

4. Authentik redirect URI

Symptom: OIDC-callback feilet fordi adm.synops.no ikke var registrert som gyldig redirect URI.

Årsak: Bare ws.synops.no var registrert i Authentik.

Løsning: Legg til adm.synops.no/auth/callback/authentik i Authentik sin provider-konfig.

Læring: Hvert subdomain trenger egen redirect URI i OIDC.

5. TLS-sertifikat

Ikke et problem: Caddy henter automatisk sertifikat for nye domener via Let's Encrypt ACME. adm.synops.no fikk sertifikat i løpet av sekunder ved første request.

Læring: Caddy sin auto-TLS er utmerket for nye subdomener. Bare legg til i Caddyfile og restart.

Arkitekturprinsipper vi trekker ut

1. Ikke hardkod hostnames i konfigfiler

ORIGIN, cookie-domene, redirect URIs — alt som binder til et spesifikt hostname gjør multi-subdomain vanskelig. Foretrekk dynamisk host-deteksjon (AUTH_TRUST_HOST=true).

2. Cookies på toppdomenet for relaterte subdomener

Når flere subdomener trenger samme sesjon, sett cookie på .synops.no. CSRF-token kan forbli host-bound (__Host- prefix) for ekstra sikkerhet.

3. Samme SvelteKit-instans for alle subdomener

Ikke kjør separate SvelteKit-instanser per subdomain. Én instans som leser hostname og tilpasser seg. Enklere deploy, delt kodebase, felles sesjon.

4. Caddy gjør routing, SvelteKit gjør logikk

Caddy ruter domene → SvelteKit. SvelteKit sjekker hostname og tilpasser innhold. Caddy trenger ingen hostname-logikk utover reverse proxy.

Hva ble gjort riktig

  • Caddy-konfig: Enkelt å legge til nytt subdomain
  • Delt SvelteKit: Ingen duplisert kode
  • Cookie-wildcard: Riktig for relaterte subdomener
  • AUTH_TRUST_HOST: Fungerer godt uten ORIGIN

Hva vi tenderer til å glemme

  • ORIGIN-variabelen — den overstyrer alt. Sjekk den først.
  • Cookie-domene — default er gjeldende hostname, ikke parent.
  • OIDC redirect URIs — må oppdateres for hvert nytt domene.
  • Be bruker slette cookies — gammel cookie fra ett domene kræsjer med ny cookie fra wildcard-domenet.

Sjekkliste for nytt subdomain

  1. DNS A-record (Hetzner DNS Console)
  2. Caddy-blokk i Caddyfile (auto-TLS)
  3. Authentik redirect URI
  4. Verifiser at ORIGIN ikke er satt (eller er kompatibel)
  5. Verifiser cookie-domene (.synops.no)
  6. Test: login → callback → riktig side
  7. Be bruker slette cookies hvis problemer