Files
verdande/internal/store/migrations/0037_sessioner_fra_en_app.sql
T
kristianwindandClaude Opus 5.5 4ef050ae04 feat(login): appen kan logge ind og bære sin session som bearer
Første trin mod en iOS-app. Appen pakker den eksisterende flade ind og henter
den fra sig selv (capacitor://localhost), så den deler aldrig origin med
serveren og får aldrig cookien tilbage. Den logger derfor ind som en browser,
med adgangskode og evt. kode, men får sin session i svaret i stedet for i en
cookie og sender den som `Authorization: Bearer`.

Det er med vilje en SESSION og ikke et API-token: den står i listen over
enheder under det navn, appen giver sig selv, kan logges ud derfra, og den når
2FA og nøgler, som et token med vilje ikke gør.

- `POST /auth/login` tager `client: "app"` og `device_name`. Svaret får
  `session_token` og ingen cookie, også mens `totp_required` er sand.
- En app-session glider: hver brug flytter udløbet frem, op til
  `VERDANDE_APP_SESSION_TTL` (180 dage) ubrugt. En browser beholder sin faste
  levetid. En halvfærdig login glider ikke; den beholder sine ti minutter.
- En bearer, der ikke er et API-token, slås op som session, men kun hvis den
  blev udstedt til appen. En browsers cookie-værdi som header må ikke blive en
  anden vej forbi SameSite og CSRF-låsen.
- CSRF-låsen genkender appens origin. Det var prøven, der fandt det: selve
  login-kaldet har intet token endnu og blev afvist som cross-site. En
  hjemmeside kan ikke skrive `Origin`-headeren, og en app-login sætter ingen
  cookie, så der er ingen session for en forfalsket anmodning at ride på.

Passkeys er udenfor i første omgang: RP-ID er bundet til domænet og kræver
apple-app-site-association på hver instans.

Migration 0037: sessions.client, device_name, idle_ttl.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 13:55:46 +02:00

20 lines
1.2 KiB
SQL

-- Sessioner fra en app.
--
-- En app logger ind som en browser gør, med adgangskode og evt. kode, og får en
-- almindelig session. Forskellen er transporten: tokenet kommer i svaret og sendes
-- som `Authorization: Bearer`, fordi en app, der henter sit UI fra sig selv, ikke
-- deler origin med serveren og derfor aldrig får cookien tilbage. At det er en
-- SESSION og ikke et API-token er hele pointen: den står i listen over enheder,
-- kan logges ud derfra, og den når indstillingerne for 2FA og nøgler, som et
-- token med vilje ikke gør.
--
-- device_name er det navn, appen giver sig selv ("Kristians iPhone"), så listen
-- siger noget, en person genkender. idle_ttl er sekunder: større end 0 betyder, at
-- sessionen glider — hver gang den bruges, flyttes udløbet frem. En browser får
-- 0 og sin faste levetid som før; en telefon, man har i lommen hver dag, må ikke
-- logge sig selv ud hver 30. dag, men en telefon, der ligger i en skuffe et halvt
-- år, skal.
ALTER TABLE sessions ADD COLUMN client TEXT NOT NULL DEFAULT 'web';
ALTER TABLE sessions ADD COLUMN device_name TEXT NOT NULL DEFAULT '';
ALTER TABLE sessions ADD COLUMN idle_ttl INTEGER NOT NULL DEFAULT 0;