Auth-middleware verifisert og fullført (oppgave 2.2)
- 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 <noreply@anthropic.com>
This commit is contained in:
parent
854ed27797
commit
8428fa45a0
5 changed files with 19 additions and 8 deletions
|
|
@ -118,6 +118,12 @@ LIVEKIT_API_SECRET=<generer med: openssl rand -hex 32>
|
||||||
# === OpenRouter ===
|
# === OpenRouter ===
|
||||||
OPENROUTER_API_KEY=<fra openrouter.ai>
|
OPENROUTER_API_KEY=<fra openrouter.ai>
|
||||||
|
|
||||||
|
# === Maskinrommet ===
|
||||||
|
DATABASE_URL=postgres://sidelinja:<POSTGRES_PASSWORD>@postgres:5432/synops
|
||||||
|
AUTHENTIK_ISSUER=https://auth.sidelinja.org/application/o/sidelinja/
|
||||||
|
AUTHENTIK_CLIENT_ID=<fra Authentik OIDC-provider>
|
||||||
|
AUTHENTIK_CLIENT_SECRET=<fra Authentik OIDC-provider>
|
||||||
|
|
||||||
# === Intern ===
|
# === Intern ===
|
||||||
# Ingen porter eksponeres utenom 80/443. Alt rutes internt via Docker-nettverket.
|
# Ingen porter eksponeres utenom 80/443. Alt rutes internt via Docker-nettverket.
|
||||||
EOF
|
EOF
|
||||||
|
|
|
||||||
|
|
@ -27,16 +27,17 @@ pub struct JwkKey {
|
||||||
pub e: String,
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct JwksKeys {
|
pub struct JwksKeys {
|
||||||
pub keys: Vec<JwkKey>,
|
pub keys: Vec<JwkKey>,
|
||||||
pub issuer: String,
|
pub issuer: String,
|
||||||
|
pub audience: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JwksKeys {
|
impl JwksKeys {
|
||||||
/// Fetch JWKS from Authentik's OIDC discovery endpoint.
|
/// Fetch JWKS from Authentik's OIDC discovery endpoint.
|
||||||
pub async fn fetch(issuer: &str) -> Result<Self, String> {
|
pub async fn fetch(issuer: &str, audience: &str) -> Result<Self, String> {
|
||||||
let jwks_url = format!("{}jwks/", issuer.trim_end_matches('/').to_owned() + "/");
|
let jwks_url = format!("{}jwks/", issuer.trim_end_matches('/').to_owned() + "/");
|
||||||
tracing::info!("Henter JWKS fra {jwks_url}");
|
tracing::info!("Henter JWKS fra {jwks_url}");
|
||||||
|
|
||||||
|
|
@ -58,6 +59,7 @@ impl JwksKeys {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
keys: jwks.keys,
|
keys: jwks.keys,
|
||||||
issuer: issuer.to_string(),
|
issuer: issuer.to_string(),
|
||||||
|
audience: audience.to_string(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,9 +170,10 @@ where
|
||||||
AuthErrorKind::InvalidToken(e)
|
AuthErrorKind::InvalidToken(e)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Validate JWT (signature, exp, iss)
|
// Validate JWT (signature, exp, iss, aud)
|
||||||
let mut validation = Validation::new(Algorithm::RS256);
|
let mut validation = Validation::new(Algorithm::RS256);
|
||||||
validation.set_issuer(&[&app_state.jwks.issuer]);
|
validation.set_issuer(&[&app_state.jwks.issuer]);
|
||||||
|
validation.set_audience(&[&app_state.jwks.audience]);
|
||||||
|
|
||||||
let token_data = decode::<Claims>(token, &decoding_key, &validation).map_err(|e| {
|
let token_data = decode::<Claims>(token, &decoding_key, &validation).map_err(|e| {
|
||||||
tracing::debug!("JWT-validering feilet: {e}");
|
tracing::debug!("JWT-validering feilet: {e}");
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,10 @@ async fn main() {
|
||||||
let issuer = std::env::var("AUTHENTIK_ISSUER")
|
let issuer = std::env::var("AUTHENTIK_ISSUER")
|
||||||
.unwrap_or_else(|_| "https://auth.sidelinja.org/application/o/sidelinja/".to_string());
|
.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
|
.await
|
||||||
.expect("Kunne ikke hente JWKS fra Authentik");
|
.expect("Kunne ikke hente JWKS fra Authentik");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,13 @@ VALUES (
|
||||||
|
|
||||||
-- =============================================================================
|
-- =============================================================================
|
||||||
-- Auth-identitet (bro mellom Authentik-sesjon og Vegards node)
|
-- 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)
|
INSERT INTO auth_identities (node_id, authentik_sub, email)
|
||||||
VALUES (
|
VALUES (
|
||||||
'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11',
|
'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11',
|
||||||
'placeholder-will-be-updated-in-task-1.5',
|
'6af61f43c6647a237cbb381ee7788376a9bc20299c2c06281d9954d763e854f0',
|
||||||
'vnotnes@pm.me'
|
'vnotnes@pm.me'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
3
tasks.md
3
tasks.md
|
|
@ -52,8 +52,7 @@ Uavhengige faser kan fortsatt plukkes.
|
||||||
## Fase 2: Maskinrommet — skjelett
|
## 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`.
|
- [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.
|
- [x] 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
|
|
||||||
- [ ] 2.3 SpacetimeDB-klient i maskinrommet: koble til STDB, skriv noder og edges via reducers.
|
- [ ] 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.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).
|
- [ ] 2.5 Flere intensjoner: `create_edge`, `update_node`, `delete_node`. Validering av tilgang (created_by eller owner/admin-edge).
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue