# Autenticazione e OAuth

> Chiavi API, OAuth 2.1 con PKCE (avvio standalone SMART on FHIR), id_token OpenID Connect, ambiti paziente SMART v2, durate dei token e ciclo di vita del consenso.

Source: https://developers.anpheros.com/it/guides/authentication

La Piattaforma Anpheros accetta tre tipi di credenziali. Ogni richiesta trasporta esattamente una di esse.

| Credenziale | Aspetto | Chi | Vede |
|---|---|---|---|
| Chiave API | `sk_test_…` (sandbox) / `sk_live_…` (produzione) | il server di un progetto | i pazienti creati dal progetto (in sandbox, inclusa la propria copia di 30 pazienti sintetici) |
| Token di accesso OAuth | `at_…` | un'applicazione che agisce per un paziente sotto un consenso | solo quel paziente, all'interno degli ambiti SMART concessi |
| Token ID Firebase | JWT | uno sviluppatore nella dashboard, o un paziente in "Connessioni" | le proprie organizzazioni / i propri record |

Inviala come `Authorization: Bearer <credential>` (le chiavi API funzionano anche come `X-Api-Key`).

## Chiavi API
- Create nel dashboard o tramite `POST /admin/projects/{id}/keys`; mostrate una sola volta; memorizzate come hash SHA-256.
- Scope: `read`, `write`. Una chiave non attraversa mai l'ambiente del suo progetto (`sk_test_` non può accedere ai dati di produzione e viceversa).
- Il limite di richieste per chiave (predefinito 600/min) viene applicato a livello di piattaforma (store condiviso), con `Retry-After` su 429. Esiste anche un limite per IP di 600/min.
- Header opzionali nelle scritture: `X-Anpheros-Author-Type`, `X-Anpheros-Author-Ref`, `X-Anpheros-Source-System`, `X-Anpheros-Origin-Id`, `X-Anpheros-Acting-As` (un Practitioner/PractitionerRole **della tua directory**), `X-Anpheros-On-Behalf-Of` (un Organization della tua directory). Popolano Provenance.

## OAuth 2.1 (SMART on FHIR, avvio standalone)
Discovery: `GET /.well-known/smart-configuration`.

1. `GET /oauth/authorize?response_type=code&client_id=…&redirect_uri=…&scope=…&state=…&code_challenge=…&code_challenge_method=S256[&purpose=treatment][&patient=<pairwise id>][&lang=ro]`
   Mostra la pagina di consenso ospitata. PKCE S256 è obbligatorio; il `redirect_uri` deve essere registrato esattamente.
2. Il paziente accede (Google o email tramite Firebase), sceglie il record (proprio o di un dipendente), la durata (30/90/180/365 giorni) e autorizza. La piattaforma rilascia un codice monouso (10 minuti).
3. `POST /oauth/token` con `grant_type=authorization_code&code=…&code_verifier=…&redirect_uri=…&client_id=…` (i client confidenziali aggiungono `client_secret`).
   Risposta: `access_token` (30 min), `refresh_token` (30 giorni, rotante), `patient` (il tuo ID pairwise per il record), `grant_id`, `scope`.
4. Refresh: `grant_type=refresh_token`. Ogni token di refresh è monouso. **La presentazione di un token di refresh usato revoca l'intera catena** (rilevamento furti). Una richiesta di refresh duplicata in parallelo viene rifiutata e può anche revocare la catena, quindi non ruotare mai in parallelo.
5. Revoca: `POST /oauth/revoke` (token + client_id). La revoca di un token di refresh revoca anche i suoi token di accesso.

Le risposte dei token trasportano `Cache-Control: no-store` e `Pragma: no-cache`, come richiesto da SMART.

### OpenID Connect (`openid fhirUser`)
Richiedi `openid fhirUser` insieme agli scope del paziente e la risposta del token contiene anche un `id_token`: un JWT firmato con RS256, con `iss` (l'URL base della piattaforma), `sub` (il tuo ID pairwise per la persona), `aud` (il tuo `client_id`), `exp`, `iat` e `fhirUser` — l'URL assoluto della risorsa Patient della persona, leggibile con il token di accesso appena ricevuto. La discovery si trova su `GET /.well-known/openid-configuration`; le chiavi pubbliche su `GET /oauth/jwks` (`kid` nell'header del token). Il parametro `nonce` non è ancora supportato (è opzionale nel flusso authorization-code). `launch/patient` e `offline_access` sono accettati; il campo `patient` della risposta del token è il contesto di lancio.

Altri tipi di grant: `client_credentials` (client confidenziali; si comporta come una chiave API), e il grant di identità first-party (solo client fidati).

### Il tuo brand sulla pagina di consenso

Un'applicazione può mostrare il proprio logo e colore d'accento sulla pagina di consenso ospitata. Impostali nella console
(Applicazioni → Brand) o con l'API admin:

```http
PUT /admin/applications/{application_id}/branding
{"logo": "data:image/png;base64,…", "brand_color": "#1D4ED8"}
```

- **Logo:** un'immagine PNG, JPEG o WebP come URI dati, fino a 64 KB. Viene controllato il contenuto, non il tipo dichiarato;
  SVG non è accettato. L'immagine viene memorizzata con l'applicazione e incorporata nella pagina, quindi la pagina di consenso
  non effettua richieste ai tuoi server.
- **Colore d'accento:** `#RRGGBB`, utilizzato per il pulsante principale. Il testo bianco su di esso deve mantenere un contrasto di almeno
  4.5:1 (WCAG AA); colori più chiari vengono rifiutati.
- Un campo che lasci vuoto rimane invariato; `null` o una stringa vuota lo rimuovono.

Il resto della pagina non cambia: la riga "Secured by Anpheros Platform", l'elenco in linguaggio semplice di
ciò che l'applicazione richiede e il banner TEST sui progetti sandbox rimangono, in modo che le persone possano sempre capire che
il consenso è gestito da Anpheros. I connettori AI (MCP) mostrano sempre la pagina Anpheros senza brand dell'applicazione.

### Scope
Scope paziente SMART v2: `patient/<Type>.<cruds>` con un filtro `?category=<code>` opzionale (l'unico filtro imposto dal server; qualsiasi altro filtro viene rifiutato al momento dell'autorizzazione). `patient/*.rs` legge tutto; `offline_access` aggiunge un token di refresh. I dati demografici del paziente e la directory sono sempre leggibili sotto un grant. Un tipo di risorsa al di fuori del grant restituisce 403; un paziente al di fuori del grant restituisce 404.

### Ciclo di vita del consenso
I consensi scadono automaticamente, possono essere revocati dal paziente in qualsiasi momento (schermata Connessioni / `/me`) e ogni lettura sotto un consenso viene registrata con l'ID dell'applicazione. I webhook `consent.granted` / `consent.revoked` notificano il progetto.

## Errori
401 credenziale sconosciuta/scaduta · 403 la credenziale esiste ma potrebbe non essere autorizzata a eseguire questa operazione · 404 la risorsa non esiste *per te* · 429 rate limited (`Retry-After`). Vedi [`errors.md`](https://developers.anpheros.com/it/guides/errors).
