From 8428fa45a094dd66929f054cc9c8eae56074b541 Mon Sep 17 00:00:00 2001 From: vegard Date: Tue, 17 Mar 2026 12:33:24 +0100 Subject: [PATCH] =?UTF-8?q?Auth-middleware=20verifisert=20og=20fullf=C3=B8?= =?UTF-8?q?rt=20(oppgave=202.2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fikser audience-validering (AUTHENTIK_CLIENT_ID som forventet aud) - Oppdaterer seed-data med reell Authentik sub for Vegard - Fikser DATABASE_URL i .env: peker nå til synops-database (ikke sidelinja) - Dokumenterer maskinrommet-miljøvariabler i produksjon.md - Markerer oppgave 2.2 som ferdig i tasks.md Verifisert på server med fem testcaser: 1. /health (public) → 200 2. /me uten token → 401 "Mangler Authorization-header" 3. /me med ugyldig token → 401 "Ugyldig token" 4. /me med gyldig JWT, ukjent sub → 401 "Ukjent brukeridentitet" 5. /me med gyldig JWT, kjent sub → 200 med node_id Co-Authored-By: Claude Opus 4.6 --- docs/setup/produksjon.md | 6 ++++++ maskinrommet/src/auth.rs | 9 ++++++--- maskinrommet/src/main.rs | 5 ++++- migrations/002_seed_data.sql | 4 ++-- tasks.md | 3 +-- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/docs/setup/produksjon.md b/docs/setup/produksjon.md index ec7246a..c1ea6b6 100644 --- a/docs/setup/produksjon.md +++ b/docs/setup/produksjon.md @@ -118,6 +118,12 @@ LIVEKIT_API_SECRET= # === OpenRouter === OPENROUTER_API_KEY= +# === Maskinrommet === +DATABASE_URL=postgres://sidelinja:@postgres:5432/synops +AUTHENTIK_ISSUER=https://auth.sidelinja.org/application/o/sidelinja/ +AUTHENTIK_CLIENT_ID= +AUTHENTIK_CLIENT_SECRET= + # === Intern === # Ingen porter eksponeres utenom 80/443. Alt rutes internt via Docker-nettverket. EOF diff --git a/maskinrommet/src/auth.rs b/maskinrommet/src/auth.rs index 8be4810..5800f6f 100644 --- a/maskinrommet/src/auth.rs +++ b/maskinrommet/src/auth.rs @@ -27,16 +27,17 @@ pub struct JwkKey { pub e: String, } -/// Cached JWKS keys fetched from Authentik at startup. +/// Cached JWKS keys and OIDC config fetched from Authentik at startup. #[derive(Debug, Clone)] pub struct JwksKeys { pub keys: Vec, pub issuer: String, + pub audience: String, } impl JwksKeys { /// Fetch JWKS from Authentik's OIDC discovery endpoint. - pub async fn fetch(issuer: &str) -> Result { + pub async fn fetch(issuer: &str, audience: &str) -> Result { let jwks_url = format!("{}jwks/", issuer.trim_end_matches('/').to_owned() + "/"); tracing::info!("Henter JWKS fra {jwks_url}"); @@ -58,6 +59,7 @@ impl JwksKeys { Ok(Self { keys: jwks.keys, issuer: issuer.to_string(), + audience: audience.to_string(), }) } @@ -168,9 +170,10 @@ where AuthErrorKind::InvalidToken(e) })?; - // Validate JWT (signature, exp, iss) + // Validate JWT (signature, exp, iss, aud) let mut validation = Validation::new(Algorithm::RS256); validation.set_issuer(&[&app_state.jwks.issuer]); + validation.set_audience(&[&app_state.jwks.audience]); let token_data = decode::(token, &decoding_key, &validation).map_err(|e| { tracing::debug!("JWT-validering feilet: {e}"); diff --git a/maskinrommet/src/main.rs b/maskinrommet/src/main.rs index 24c629d..b427137 100644 --- a/maskinrommet/src/main.rs +++ b/maskinrommet/src/main.rs @@ -54,7 +54,10 @@ async fn main() { let issuer = std::env::var("AUTHENTIK_ISSUER") .unwrap_or_else(|_| "https://auth.sidelinja.org/application/o/sidelinja/".to_string()); - let jwks = JwksKeys::fetch(&issuer) + let client_id = std::env::var("AUTHENTIK_CLIENT_ID") + .expect("AUTHENTIK_CLIENT_ID må være satt"); + + let jwks = JwksKeys::fetch(&issuer, &client_id) .await .expect("Kunne ikke hente JWKS fra Authentik"); diff --git a/migrations/002_seed_data.sql b/migrations/002_seed_data.sql index 613edd1..6f1f336 100644 --- a/migrations/002_seed_data.sql +++ b/migrations/002_seed_data.sql @@ -19,13 +19,13 @@ VALUES ( -- ============================================================================= -- Auth-identitet (bro mellom Authentik-sesjon og Vegards node) --- authentik_sub oppdateres når Authentik konfigureres i oppgave 1.5. +-- authentik_sub er Authentik sin OIDC sub-claim (SHA256-hash av intern UUID). -- ============================================================================= INSERT INTO auth_identities (node_id, authentik_sub, email) VALUES ( 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11', - 'placeholder-will-be-updated-in-task-1.5', + '6af61f43c6647a237cbb381ee7788376a9bc20299c2c06281d9954d763e854f0', 'vnotnes@pm.me' ); diff --git a/tasks.md b/tasks.md index 94a1267..e1d9135 100644 --- a/tasks.md +++ b/tasks.md @@ -52,8 +52,7 @@ Uavhengige faser kan fortsatt plukkes. ## Fase 2: Maskinrommet — skjelett - [x] 2.1 Rust-prosjekt: opprett `maskinrommet/` med axum, tokio, sqlx (PG), serde. Dockerfile. Kompilerer og starter. Ref: `docs/retninger/maskinrommet.md`. -- [~] 2.2 Auth-middleware: valider Authentik JWT-tokens, slå opp `auth_identities` → node_id. Returner 401 for ugyldige tokens. - > Påbegynt: 2026-03-17T12:20 +- [x] 2.2 Auth-middleware: valider Authentik JWT-tokens, slå opp `auth_identities` → node_id. Returner 401 for ugyldige tokens. - [ ] 2.3 SpacetimeDB-klient i maskinrommet: koble til STDB, skriv noder og edges via reducers. - [ ] 2.4 Skrivestien: `POST /intentions/create_node` — valider, skriv STDB (instant), spawn async PG-skriving. Returner node_id umiddelbart. - [ ] 2.5 Flere intensjoner: `create_edge`, `update_node`, `delete_node`. Validering av tilgang (created_by eller owner/admin-edge).