# Autenticazione tramite portale e proxy fidato Questa è la modalità **upstream** usata dall'integrazione Omics. Non è il login OIDC diretto di ThothII: l'utente accede a Omics come già fa, poi sceglie Datamart Builder e trova ThothII già autenticato. Non deve essere creato un utente locale ThothII né effettuato un secondo scambio OIDC dall'applicazione embedded. ## Il confine di fiducia ```mermaid sequenceDiagram actor U as Utente già autenticato participant N as Nginx Omics participant D as Django Omics participant T as Core ThothII upstream U->>D: Apri Datamart Builder D-->>U: Pagina autorizzata con mount React U->>N: GET /datamart-builder/api/me (cookie Omics) N->>D: Subrequest interna /datamart-builder/api-auth D-->>N: 200 + identità verificata, oppure 403 N->>T: GET /me + intestazioni normalizzate (solo se autorizzato) T-->>U: Identità e permessi applicativi, oppure rifiuto ``` L'header e l'adapter JavaScript non autenticano nessuno. Il backend accetta una richiesta upstream solo con un'identità valida ricevuta da un percorso di rete fidato. Gli header non sono firmati da ThothII: la protezione è il proxy che verifica la sessione e sovrascrive l'identità, insieme all'isolamento del core. Un core upstream direttamente raggiungibile da client non fidati è una falla, non una modalità alternativa di accesso. ## Configurazione del core Per Omics il descrittore pubblico deve contenere: ```yaml shell: mode: embedded defaultLocale: en adapter: omics-portal ``` Separatamente, il **processo core** deve ricevere `AUTH_MODE=upstream`. Definirlo nell'override Compose approvato e incluso nell'installazione; una variabile nel file di interpolazione `.env` non viene passata automaticamente al container: ```yaml services: core: environment: AUTH_MODE: upstream ``` È solo il frammento di selezione auth, non un file Compose completo né una configurazione di rete sufficiente. Non aggiunge porte pubbliche. Condizioni obbligatorie: 1. Nessun `auth.yaml` local/OIDC deve essere effettivamente montato al percorso letto dal core (default `/run/thothii-auth/auth.yaml`). Se è presente insieme ad `AUTH_MODE`, l'avvio fallisce. Non impostare `AUTH_MODE=local` o `oidc`: questi due modi si selezionano dal file, non da quella variabile. 2. Non configurare `authentication.runtimeProjection` per questo percorso: è la proiezione delle configurazioni cookie local/OIDC, non l'identità Omics. Nemmeno `THT_AUTH_RUNTIME_PROJECTION_ROOT` deve attivarla nel core. 3. Il descrittore e Compose base continuano a richiedere `authentication.configDirectory` e `THT_AUTH_CONFIG_ROOT` coerenti. Per una nuova installazione upstream usare una directory dedicata senza `auth.yaml`, non cancellare la configurazione di un'installazione esistente. I cambi di modalità richiedono un piano separato. 4. Non esiste `tht auth configure --mode upstream`: il CLI configura gli utenti locali o l'OIDC diretto. Conservare il percorso proxy già operativo per Omics. 5. `profile: server`, storage delle sessioni e `THOTH_PUBLIC_EXPOSURE` hanno propri vincoli, che rimangono attivi. La shell embedded non li soddisfa automaticamente. Il sorgente considera upstream un percorso di compatibilità con il proxy; è quello usato dall'integrazione Omics corrente. `none` e `mock` sono per sviluppo/test, non soluzioni a errori di configurazione in produzione. ## Intestazioni richieste all'ingresso del core | Header | Regola ThothII | Valore Omics | | --- | --- | --- | | `X-Thoth-Principal-Issuer` | Stringa stabile, obbligatoria | `portal` | | `X-Thoth-Principal-Subject` | ID stabile dell'utente, obbligatorio | `str(user.pk)` Django | | `X-Thoth-Principal-Display-Name` | Facoltativo, se presente non vuoto | Nome completo o username | | `X-Thoth-Is-Admin` | Obbligatorio: `0`, `1`, `false` o `true` | Risultato di `is_authentik_admin(user)` | Le stringhe sono ripulite degli spazi esterni, devono avere al massimo 512 caratteri e non contenere caratteri di controllo. Header mancanti o invalidi producono 401. `false`/`0` assegna il ruolo `user`; `true`/`1` assegna `user` e `admin`. Il core espande i permessi dal proprio catalogo, non da un array inviato dal browser. `/me` richiede `session.use`. La coppia `(issuer, subject)` identifica il proprietario delle sessioni. Non sostituire il subject con un nome visualizzato o un'email modificabile; non cambiare issuer/subject di utenti esistenti per correggere un problema grafico. Passare da identità `portal` a identità OIDC diretta non migra la proprietà dei dati. ## Omics: percorsi e componenti esatti | Percorso | Destinazione e funzione | | --- | --- | | `/kokoro/datamart-builder/` | Pagina Django con `datamart_builder.access` | | `/datamart-builder/config.js` | Config pubblico del frontend, senza cache | | `/datamart-builder/assets/…` | Asset frontend risolti dal manifest Vite | | `/datamart-builder/api/…` | Nginx con `auth_request`, poi core senza il prefisso | | `/_thothii_auth` | Location Nginx interna, non un login pubblico | | `/datamart-builder/api-auth` | Django verifica sessione Omics e capability | Nel repository Omics: - `kokoro/datamart_catalog_views.py`: `DatamartBuilderView` e `datamart_builder_api_auth`; la verifica API risponde 200 o 403, anche 403 quando la sessione è assente/scaduta. Non trasforma l'API in una pagina di login. - `nginx/nginx.conf`: API direttamente a `thothii-core:8787`, config e asset a `thothii-frontend:8080`; verificare alias e reti Docker effettivi sul server. - `templates/kokoro/datamart_builder.html`: mount, config e override del prefisso. - `kokoro/templatetags/vite.py`: manifest da `http://thothii-frontend:8080/.vite/manifest.json`, cache Django di 30 secondi. Nginx usa il cookie Omics nella subrequest a Django. Sulle richieste al core sovrascrive i quattro header con i risultati della verifica e rimuove `Cookie`, `Authorization` e `X-Authenticated-User`. Nessuna password o token del portale deve essere copiato nel config pubblico, nello snapshot adapter o in Web Storage. `GET /datamart-builder/api/me` restituisce l'identità e i permessi; in upstream `session` e `csrfToken` sono `null`: non viene creata una sessione-cookie ThothII. ## Non confondere i due percorsi proxy L'esempio generico `deploy/nginx-authenticated-proxy.conf.example` usa **due hop**: proxy host → frontend Nginx ThothII → core. Sul tratto privato verso il frontend trasporta `X-Thoth-Trusted-Principal-*` e `X-Thoth-Trusted-Is-Admin`; il frontend li converte nei quattro header del core e li elimina prima dell'inoltro. Omics usa invece **Nginx Omics → core direttamente** per le API e invia gli header normalizzati senza `Trusted`. Non incollare l'esempio a due hop in questa location: la famiglia di header sbagliata produce 401. In entrambi i casi i valori devono venire dalla verifica server, mai dagli header del client. Il tratto privato del percorso generico deve essere inaccessibile ai client non fidati. ## Origine delle richieste e stream Browser e API devono restare sullo stesso origin. Il frontend accetta `/api` o un prefisso same-origin come `/datamart-builder/api`, non un URL `http://core:8787`. In upstream le scritture con `Origin` sono confrontate con protocollo e Host percepiti dal core; non usano il token CSRF della sessione ThothII local/OIDC. Le richieste senza Origin hanno il trattamento non-browser: l'autenticazione del proxy rimane indispensabile anche per esse. Nel Nginx Omics esaminato il TLS termina a monte e una mappa **esatta** converte `https://aritmolab.policlinicosandonato.it` in `http://aritmolab.policlinicosandonato.it` per il confronto interno. Le altre origini rimangono invariate e devono essere negate quando non coincidono. È una scelta specifica della topologia corrente, non un modello da estendere con wildcard, cancellazione di Origin o riscrittura incondizionata. Verificare Host/protocollo al core e i dinieghi cross-origin nella topologia realmente rilasciata. La location API disabilita buffering/cache per SSE e mantiene timeout lunghi. `auth_request` verifica ogni nuova richiesta, ma non interrompe istantaneamente uno stream già aperto quando il portale revoca l'utente. ThothII ricontrolla `/me` al ritorno alla pagina e alla riconnessione degli eventi; non promettere revoca istantanea fra tutte le schede. ## Logout, rientro e diagnosi In embedded logout e successivo login sono di Omics. ThothII non chiama `/auth/logout`, non cancella il cookie Django e non apre un suo login. Il rifiuto 401/403 di `/me` rimuove lo stato protetto e richiede il rientro dal portale. Un 403 su una singola operazione non equivale al logout dell'applicazione. | Sintomo | Controllo mirato | | --- | --- | | Secondo header | Config servito: deve essere embedded, non full | | Nessuna UI e errore preferenze | Selettore Omics `data-lang` e `html data-bs-theme` | | `/me` 401 dal core | Header obbligatori, famiglia Trusted/normalizzata, percorso proxy | | `/me` 403 dal proxy | Sessione Omics e capability `datamart_builder.access` | | `/me` funziona ma POST 403 | Distinguere permesso operativo da mismatch Origin/Host/protocollo | | 502 o asset assenti | Alias/rete Docker e manifest Vite; attesa cache manifest 30 s | | Avvio core rifiutato | Coesistenza di `auth.yaml` o runtime projection con `AUTH_MODE` | | Logout full seguito da rientro IdP immediato | Il logout ThothII non è logout globale OIDC | Non raccogliere cookie, token, segreti o dump completi delle configurazioni nei report. Registrare codici HTTP, nomi dei percorsi, revisioni e risultati dei test. Consegna e rilascio: [procedura Omics](../operations/shell-and-localization.md#verifica-prima-del-deploy-server). Collaudo obbligatorio: [matrice di accettazione](../testing/authentication-manual-acceptance.md).