
# Sicurezza web delle pagine ospitate e dell'API frontend

L'accesso ospitato, il portale account, le pagine email (verifica, reimpostazione della password, invito) e l'API del browser che esse chiamano seguono una base di sicurezza web fissa su ogni piano. Queste protezioni non sono impostazioni che puoi disattivare. L'unica impostazione che controlli è quali origini web possono chiamare dal browser gli endpoint OAuth.

## Cross-site request forgery (CSRF)

Le richieste che modificano lo stato vengono verificate prima che venga letto o modificato qualsiasi dato:

- **Controllo dell'origine.** Una richiesta che modifica lo stato verso l'API di accesso ospitata o verso una pagina di verifica o reimpostazione deve includere un header `Origin` esattamente uguale all'host di accesso dell'ambiente. Qualsiasi altra origine viene rifiutata con `origin_not_allowed`.
- **Schermata di consenso.** Un invio di form sulla schermata di consenso viene rifiutato quando il suo `Origin` non è l'host della pagina stessa, oppure quando `Sec-Fetch-Site` è presente e non vale `same-origin`.
- **Token dei form.** Ogni transazione di accesso e ogni form email ha un proprio token CSRF, derivato con HMAC-SHA256 da una chiave per ambiente. L'API di accesso lo attende nell'header `Idp-Csrf-Token`; il token di un form non funziona per un altro. I token sono confrontati in tempo costante.
- **Cookie.** I cookie che trasportano lo stato di accesso usano `SameSite=Lax` (vedi sotto), quindi una richiesta avviata da un altro sito non li invia.

## Richieste cross-origin (CORS)

CORS viene gestito solo sugli endpoint OAuth che un'applicazione browser chiama: l'endpoint dei token, di revoca, della richiesta di autorizzazione pushed e di userinfo. Si applica solo alle applicazioni single-page pubbliche (tipo `spa`).

- Imposta le origini consentite per applicazione con `allowed_web_origins` (`https://host[:port]`, al massimo 20, senza wildcard). Vedi [Crea un'applicazione](/docs/api/management/applications/create).
- La richiesta di preflight del browser non indica quale applicazione sta chiamando, quindi riceve risposta dall'unione delle origini consentite delle applicazioni single-page pubbliche attive dell'ambiente. La richiesta effettiva viene poi verificata rispetto all'elenco di origini dell'applicazione che chiama.
- Un'origine fuori dall'elenco di quell'applicazione viene rifiutata con `403 origin_not_allowed` e non riceve alcun header `Access-Control-Allow-Origin`.
- Un'origine consentita viene restituita esattamente così com'è. `*` e `null` non vengono mai inviati, `Access-Control-Allow-Credentials` non viene mai inviato, e ogni risposta cross-origin include `Vary: Origin`.
- Le richieste dall'host di accesso stesso non sono cross-origin e non sono interessate.

## Reindirizzamenti dopo l'accesso

Se usi l'SDK Next.js, `returnTo` deve essere un percorso della tua app. Un URL completo o un valore come `//evil.example` viene ignorato e l'utente finisce su `/`. Vedi [SDK Next.js](/docs/sdk/nextjs).

## Header di sicurezza

Le pagine ospitate impostano questi header in ogni risposta:

| Header | Valore |
|---|---|
| `Content-Security-Policy` | `default-src 'none'`; script solo con un nonce nuovo per ogni risposta; `style-src 'self'`; `connect-src 'self'`; `frame-ancestors 'none'`; `base-uri 'none'`; `object-src 'none'`; `upgrade-insecure-requests`; Trusted Types richiesti per gli script |
| `Reporting-Endpoints` e `report-to` | Le violazioni della policy vengono segnalate a `/u/csp-report` sullo stesso host |
| `X-Frame-Options` | `DENY`: le pagine ospitate non possono essere incorporate in un frame |
| `X-Content-Type-Options` | `nosniff` |
| `Referrer-Policy` | `no-referrer` |
| `Cross-Origin-Opener-Policy` | `same-origin` |
| `Permissions-Policy` | Fotocamera, microfono, geolocalizzazione, pagamento, USB, seriale, HID e Bluetooth sono disattivati; le richieste di passkey sono consentite per la pagina stessa |
| `Cache-Control` | `no-store` |

La policy non consente script inline né parole chiave `unsafe-`. L'invio dei form è limitato all'host della pagina; sulla schermata di consenso la policy consente anche l'indirizzo di reindirizzamento dell'applicazione che chiede l'accesso, così che la decisione possa tornare a essa.

L'endpoint di segnalazione accetta solo segnalazioni di violazione del browser di al massimo 8 KiB, ed è soggetto a limite di frequenza per indirizzo IP. Le segnalazioni vengono conteggiate per direttiva. Quando vengono registrate non contengono query string, frammenti o informazioni sull'utente.

### Strict-Transport-Security

- Gli host dell'ambiente su `keenauth.app` inviano `max-age=63072000; includeSubDomains`.
- Un [dominio personalizzato](/docs/guides/custom-domains) invia solo `max-age=63072000`, senza `includeSubDomains`. KeenAuth non può decidere per gli altri sottodomini del tuo dominio, quindi questa scelta resta a te.

## Cookie

I cookie di stato dell'accesso hanno nomi con il prefisso `__Host-`, quindi un browser li accetta solo su HTTPS, con `Path=/` e senza attributo `Domain`. Non possono essere impostati da un sottodominio fratello.

| Cookie | Flag | Scopo |
|---|---|---|
| `__Host-idp_session` | `Secure`, `HttpOnly`, `SameSite=Lax` | La sessione dell'utente. La sua durata termina alla scadenza assoluta della sessione |
| `__Host-idp_device` | `Secure`, `HttpOnly`, `SameSite=Lax` | Riconoscimento del dispositivo |
| `__Host-idp_ltx` e `__Host-idp_azr_*` | `Secure`, `HttpOnly`, `SameSite=Lax` | Associa un tentativo di accesso o di autorizzazione al browser che lo ha avviato |
| `__Host-idp_fed_bind` | `Secure`, `HttpOnly`, `SameSite=None` | Associazione di breve durata per l'accesso SAML aziendale. Il provider di identità invia i dati di ritorno da un altro sito, quindi `Lax` lo scarterebbe |

I valori dei cookie non sono leggibili dagli script della pagina (`HttpOnly`).

## Correlati

- [Sicurezza dell'accesso alla dashboard](/docs/security/dashboard-access)
- [Isolamento dei tenant](/docs/security/tenant-isolation)
- [Personalizza le tue pagine di accesso](/docs/guides/branding)
