瀏覽代碼

Aggiornamento README con la configurazione per keycloak

main
Lorenzo Pollutri 3 週之前
父節點
當前提交
76568ee857
共有 1 個文件被更改,包括 118 次插入49 次删除
  1. +118
    -49
      README.md

+ 118
- 49
README.md 查看文件

@@ -321,61 +321,130 @@ Punti chiave:
L'autorizzazione **non** è gestita dall'app Next ma da **Apache `mod_auth_openidc`** (Keycloak), già usato dal captive portal. L'app non contiene codice di auth: si fida del gate del reverse proxy.

### Cosa è protetto
- **Pagina `/cards/admin`** e **API di scrittura**: accessibili solo all'utente Keycloak con `preferred_username == admin`.
- **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`).
- **Pagina `/cards/admin`** e **API di scrittura**: accessibili solo agli utenti Keycloak che appartengono al **realm role `cpc-admin`**. Più amministratori si gestiscono assegnando/rimuovendo il ruolo agli utenti, senza toccare Apache.
- **Non autenticato** su `/cards/admin` → mandato al **login Keycloak**; al ritorno, se ha il ruolo `cpc-admin` entra, altrimenti **redirect alla home** (nessun errore).
- **Autenticato ma senza ruolo `cpc-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`.
- Protette su **tutti i metodi**: `/cards/api/upload`, `/cards/api/transcode`, `/cards/api/admin/*` (incluse le GET come backup e stato factory-preset).

### Configurazione Apache
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:
```apache
# Pagina admin: non autenticato → login Keycloak; autenticato non-admin → home
<Location "/cards/admin">
AuthType openid-connect
OIDCUnAuthAction auth
Require claim preferred_username:admin
ErrorDocument 403 https://<host>/cards/
</Location>
### Setup iniziale (step-by-step)

#### A — Configurazione Keycloak

1. Apri l'**Admin Console** di Keycloak.
2. Seleziona il realm del captive portal (es. `interceptor1`).
3. **Realm roles** → bottone **Create role** → name: `cpc-admin` → **Save**. (Da fare una sola volta.)
4. Per ogni utente che deve diventare amministratore: **Users** → seleziona l'utente → tab **Role mapping** → **Assign role** → cerca e seleziona `cpc-admin` → **Assign**.
5. *(Verifica opzionale)* **Clients** → `interceptor1-client` (o il nome del tuo client) → tab **Client scopes** → **Evaluate** → scegli un utente con `cpc-admin` → **Generated access token** → controlla che `realm_access.roles` contenga `cpc-admin`.

#### B — Configurazione Apache (vhost del captive portal)

Apri il file vhost (quello con i segnaposto `@@@REDIRECT@@@`, `@@@DIRECTORY@@@`, …).

1. **Blocco proxy globale `/cards`** — fuori dai vhost, in cima al file (dopo il `LoadModule` di `mod_auth_openidc`):
```apache
<Location "/cards">
Header always unset X-Frame-Options
Header set X-Frame-Options "ALLOWALL"
Header always set Content-Security-Policy "frame-ancestors 'self' *"

ProxyPass "http://localhost:3000/cards" connectiontimeout=5 timeout=600 keepalive=on
ProxyPassReverse "http://localhost:3000/cards"

RewriteCond %{HTTPS} on
RewriteRule .* - [E=DASH_PROTO:https]
RewriteCond %{HTTPS} off
RewriteRule .* - [E=DASH_PROTO:http]

RequestHeader set X-Forwarded-Proto %{DASH_PROTO}e
</Location>
```
`<Location "/cards">` **senza** slash finale: intercetta sia `/cards` sia `/cards/...`. `ProxyPass` con target `/cards` (non `/`): preserva il prefisso.

2. **In ENTRAMBI i vhost (`:80` e `:443`)** cambia il cookie path:
```apache
OIDCCookiePath /general # ← era così
OIDCCookiePath / # ← cambia in questo
```
Senza questa modifica il cookie del captive non raggiunge `/cards` e ricevi `401` anche se sei loggato.

3. **In ENTRAMBI i vhost** aggiungi i blocchi di protezione **dopo** le `<Location /general/...>` esistenti e **prima** di `OIDCRedirectURI`:
```apache
# Pagina admin: non autenticato → login Keycloak; autenticato senza ruolo → home
<Location "/cards/admin">
AuthType openid-connect
OIDCUnAuthAction auth
Require claim realm_access.roles:cpc-admin
ErrorDocument 403 https://@@@REDIRECT@@@/cards/
</Location>

# cards/portals: GET pubblica, scrittura solo admin
<Location "/cards/api/cards">
<LimitExcept GET HEAD>
AuthType openid-connect
OIDCUnAuthAction 401
Require claim realm_access.roles:cpc-admin
</LimitExcept>
</Location>
<Location "/cards/api/portals">
<LimitExcept GET HEAD>
AuthType openid-connect
OIDCUnAuthAction 401
Require claim realm_access.roles:cpc-admin
</LimitExcept>
</Location>

# upload / transcode / admin: tutti i metodi solo admin
<Location "/cards/api/upload">
AuthType openid-connect
OIDCUnAuthAction 401
Require claim realm_access.roles:cpc-admin
</Location>
<Location "/cards/api/transcode">
AuthType openid-connect
OIDCUnAuthAction 401
Require claim realm_access.roles:cpc-admin
</Location>
<Location "/cards/api/admin">
AuthType openid-connect
OIDCUnAuthAction 401
Require claim realm_access.roles:cpc-admin
</Location>
```

4. **Valida la sintassi e ricarica Apache:**
```bash
apachectl configtest
systemctl reload apache2 # o `apachectl graceful`, o l'equivalente del tuo sistema
```

#### C — Test (in finestra incognito, sessione pulita)

1. Vai su `https://<host>/cards/admin` da non autenticato → ti porta al login Keycloak.
2. Login con un utente **senza** ruolo `cpc-admin` → ritorni e finisci a `https://<host>/cards/` (home, 403→redirect).
3. Login con un utente **con** ruolo `cpc-admin` → ti entra nell'admin; salvataggi, upload, backup devono funzionare.
4. `GET https://<host>/cards/api/files?name=...` da non autenticato deve restare pubblico (immagine visibile a tutti gli utenti del captive).

### Note tecniche

- **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 senza ruolo → 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 e con il ruolo `cpc-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 `/`).

# API: GET pubblica, scrittura solo admin
<Location "/cards/api/cards">
<LimitExcept GET HEAD>
AuthType openid-connect
OIDCUnAuthAction 401
Require claim preferred_username:admin
</LimitExcept>
</Location>
<Location "/cards/api/portals">
<LimitExcept GET HEAD>
AuthType openid-connect
OIDCUnAuthAction 401
Require claim preferred_username:admin
</LimitExcept>
</Location>
### Aggiungere o rimuovere amministratori (dopo il setup iniziale)

# upload / transcode / admin: tutti i metodi solo admin
<Location "/cards/api/upload">
AuthType openid-connect
OIDCUnAuthAction 401
Require claim preferred_username:admin
</Location>
<Location "/cards/api/transcode">
AuthType openid-connect
OIDCUnAuthAction 401
Require claim preferred_username:admin
</Location>
<Location "/cards/api/admin">
AuthType openid-connect
OIDCUnAuthAction 401
Require claim preferred_username:admin
</Location>
Si fa **interamente in Keycloak**, senza toccare Apache o l'app:

- **Aggiungere un admin**: Users → utente → tab **Role mapping** → **Assign role** → `cpc-admin`.
- **Rimuovere un admin**: stessa pagina → rimuovi `cpc-admin` da quell'utente.

L'utente deve fare **logout/login** (o attendere il refresh del token) perché il cambio di ruolo compaia nel claim. La regola Apache resta invariata.

**Variante rapida senza Keycloak** — se preferisci una whitelist hardcoded di username per pochi utenti fissi, sostituisci la riga `Require claim realm_access.roles:cpc-admin` (in tutti i blocchi) con:
```apache
Require claim preferred_username:admin alice bob
```
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 `/`).
(I valori multipli sono in OR.) Ogni modifica richiede di toccare il vhost e ricaricare Apache.

### 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).


Loading…
取消
儲存