| @@ -322,7 +322,8 @@ L'autorizzazione **non** è gestita dall'app Next ma da **Apache `mod_auth_openi | |||||
| ### Cosa è protetto | ### Cosa è protetto | ||||
| - **Pagina `/cards/admin`** e **API di scrittura**: accessibili solo all'utente Keycloak con `preferred_username == admin`. | - **Pagina `/cards/admin`** e **API di scrittura**: accessibili solo all'utente Keycloak con `preferred_username == admin`. | ||||
| - Chi non è autenticato o non è admin → **redirect alla home** del portale (nessun errore). | |||||
| - **Non autenticato** su `/cards/admin` → mandato al **login Keycloak**; al ritorno, se è `admin` entra, altrimenti **redirect alla home** (nessun errore). | |||||
| - **Autenticato ma non admin** → redirect alla home (`403`). | |||||
| - **Restano pubbliche** (servono al portale per tutti gli utenti WiFi): le **GET** di `/cards/api/cards` e `/cards/api/portals`, e `/cards/api/files`, `/cards/api/fonts`. | - **Restano pubbliche** (servono al portale per tutti gli utenti WiFi): le **GET** di `/cards/api/cards` e `/cards/api/portals`, e `/cards/api/files`, `/cards/api/fonts`. | ||||
| - Protette su **tutti i metodi**: `/cards/api/upload`, `/cards/api/transcode`, `/cards/api/admin/*` (incluse le GET come backup e stato factory-preset). | - Protette su **tutti i metodi**: `/cards/api/upload`, `/cards/api/transcode`, `/cards/api/admin/*` (incluse le GET come backup e stato factory-preset). | ||||
| @@ -330,12 +331,11 @@ L'autorizzazione **non** è gestita dall'app Next ma da **Apache `mod_auth_openi | |||||
| 1. Il cookie di sessione OIDC deve coprire `/cards`: nel vhost imposta `OIDCCookiePath /` (non un sotto-percorso come `/general`), altrimenti `mod_auth_openidc` non vede la sessione su `/cards`. | 1. Il cookie di sessione OIDC deve coprire `/cards`: nel vhost imposta `OIDCCookiePath /` (non un sotto-percorso come `/general`), altrimenti `mod_auth_openidc` non vede la sessione su `/cards`. | ||||
| 2. Aggiungi nel/i vhost (dove l'OIDC è configurato) i blocchi di protezione: | 2. Aggiungi nel/i vhost (dove l'OIDC è configurato) i blocchi di protezione: | ||||
| ```apache | ```apache | ||||
| # Pagina admin: solo utente 'admin'; non autenticato/non admin → home | |||||
| # Pagina admin: non autenticato → login Keycloak; autenticato non-admin → home | |||||
| <Location "/cards/admin"> | <Location "/cards/admin"> | ||||
| AuthType openid-connect | AuthType openid-connect | ||||
| OIDCUnAuthAction 401 | |||||
| OIDCUnAuthAction auth | |||||
| Require claim preferred_username:admin | Require claim preferred_username:admin | ||||
| ErrorDocument 401 https://<host>/cards/ | |||||
| ErrorDocument 403 https://<host>/cards/ | ErrorDocument 403 https://<host>/cards/ | ||||
| </Location> | </Location> | ||||
| @@ -372,7 +372,10 @@ L'autorizzazione **non** è gestita dall'app Next ma da **Apache `mod_auth_openi | |||||
| Require claim preferred_username:admin | Require claim preferred_username:admin | ||||
| </Location> | </Location> | ||||
| ``` | ``` | ||||
| Note: `OIDCUnAuthAction 401` fa sì che il non autenticato riceva `401` (poi `ErrorDocument` → home) invece di essere mandato al login. L'`ErrorDocument` di redirect è solo sulla pagina admin: sulle API un accesso non autorizzato riceve `401/403` (corretto per una chiamata API). L'admin, una volta autenticato via Keycloak come utente `admin` (tramite il normale flusso del portale), invia il cookie di sessione con le richieste e può salvare/caricare/fare backup. | |||||
| Note: | |||||
| - **Pagina admin** usa `OIDCUnAuthAction auth`: il non autenticato viene mandato al login Keycloak. Questo è anche ciò che **riemette il cookie di sessione al path `/`** dopo aver impostato `OIDCCookiePath /`, sanando il classico `401` "anche da autenticato". Solo `ErrorDocument 403` (autenticato non-admin → home): **non** usare `ErrorDocument 401`, perché Apache non sa fare un redirect su un `401` (genera l'errore "a 401 error was encountered while trying to use an ErrorDocument"). | |||||
| - **API** usano `OIDCUnAuthAction 401` e **nessun** `ErrorDocument`: un accesso non autorizzato riceve `401/403` (corretto per una chiamata fetch, che non va rediretta). L'admin, già autenticato come utente `admin`, invia il cookie di sessione con le richieste e può salvare/caricare/fare backup. | |||||
| - Niente VirtualHost dedicato: la protezione sta nello stesso vhost dove l'OIDC è configurato (la sessione è condivisa col captive portal via cookie a path `/`). | |||||
| ### Pagine inesistenti → redirect alla home | ### Pagine inesistenti → redirect alla home | ||||
| Qualsiasi percorso non corrispondente a una pagina o API reale del progetto **non mostra una schermata d'errore**: viene reindirizzato alla home. È gestito lato Next da una rotta catch-all ([app/[...not_found]/page.tsx](app/%5B...not_found%5D/page.tsx)) che esegue `redirect('/')`. Le rotte reali (`/`, `/admin`, `/api/*`) hanno priorità; solo i path inesistenti finiscono lì. Le API inesistenti restano `404` (il redirect riguarda le pagine). | Qualsiasi percorso non corrispondente a una pagina o API reale del progetto **non mostra una schermata d'errore**: viene reindirizzato alla home. È gestito lato Next da una rotta catch-all ([app/[...not_found]/page.tsx](app/%5B...not_found%5D/page.tsx)) che esegue `redirect('/')`. Le rotte reali (`/`, `/admin`, `/api/*`) hanno priorità; solo i path inesistenti finiscono lì. Le API inesistenti restano `404` (il redirect riguarda le pagine). | ||||