# Come implementare il consenso del paziente con SMART on FHIR

> Tutorial: SMART on FHIR con OAuth 2.1 e PKCE passo dopo passo — discovery, registrazione dell'app, schermata di consenso, scambio di token, scope applicati, rotazione del refresh e revoca — e cosa implementa Anpheros.

Source: https://developers.anpheros.com/it/guides/smart-on-fhir-backend

**SMART on FHIR è il modo standard con cui un'applicazione ottiene il permesso di una persona di accedere al proprio record FHIR: OAuth 2.1 con PKCE per l'autorizzazione, scope che indicano esattamente cosa può essere letto o scritto, e un documento di discovery che dice all'applicazione dove andare.** Questo tutorial esegue l'intero flusso contro Anpheros, passo dopo passo con `curl`: discovery, registrazione di un'applicazione, invio della persona alla schermata di consenso, scambio del codice, chiamata dell'API all'interno degli scope concessi, refresh e cosa succede quando la persona revoca l'accesso. Anpheros è il backend SMART on FHIR: ospita il server di autorizzazione, la schermata di consenso e il server FHIR R4, quindi non è necessario scrivere alcuna UI di login o consenso propria.

## Perché il consenso e non solo una chiave API

Una chiave API raggiunge i pazienti creati dal tuo progetto. Il record esistente di una persona (i propri dati, raccolti da altre app, cliniche e laboratori) è loro da condividere. Con SMART on FHIR:

- la persona vede, nella propria lingua, quale applicazione chiede, cosa vuole leggere o scrivere, per quale scopo e per quanto tempo;
- la tua applicazione ottiene solo quei tipi di risorse e azioni, e solo per quel singolo record;
- ogni accesso viene registrato e visibile alla persona, che può revocarlo in qualsiasi momento;
- la concessione viene anche memorizzata come una risorsa FHIR `Consent`.

Il modello sottostante è descritto in [Healthcare API with patient consent](https://developers.anpheros.com/it/guides/healthcare-api-patient-consent) e [Consent and access model](https://developers.anpheros.com/it/guides/consent).

## Passaggio 1: discovery

```bash
curl https://platform.anpheros.com/fhir/R4/.well-known/smart-configuration
```

La risposta elenca gli endpoint e ciò che il server supporta (abbreviato):

```json
{"issuer": "https://platform.anpheros.com",
 "authorization_endpoint": "https://platform.anpheros.com/oauth/authorize",
 "token_endpoint": "https://platform.anpheros.com/oauth/token",
 "revocation_endpoint": "https://platform.anpheros.com/oauth/revoke",
 "code_challenge_methods_supported": ["S256"],
 "scopes_supported": ["patient/*.rs", "patient/Patient.r", "patient/Observation.rs", "patient/Observation.rs?category=laboratory",
                      "patient/Observation.rs?category=vital-signs", "patient/Observation.c", "patient/Condition.rs",
                      "patient/MedicationStatement.rs", "patient/DocumentReference.rs", "patient/AllergyIntolerance.rs",
                      "offline_access", "launch/patient", "openid", "fhirUser"],
 "capabilities": ["launch-standalone", "client-public", "client-confidential-symmetric", "permission-patient",
                  "permission-offline", "context-standalone-patient", "sso-openid-connect"]}
```

Le librerie client SMART leggono questo documento e non necessitano di ulteriori configurazioni.

## Passaggio 2: Registra la tua applicazione

Nel [dashboard](https://platform.anpheros.com/dashboard/), apri il tuo progetto e aggiungi un'applicazione con il suo redirect URI. Oppure tramite l'Admin API:

```bash
curl -X POST https://platform.anpheros.com/admin/projects/$PROJECT/applications \
     -H "Authorization: Bearer $FIREBASE_ID_TOKEN" -H "Content-Type: application/json" -d '{
  "name": "CardioAI", "client_type": "public",
  "redirect_uris": ["https://cardio.example/callback"],
  "purpose": "cardiology follow-up", "privacy_url": "https://cardio.example/privacy"
}'
```

```json
{"id": "app_…", "name": "CardioAI", "client_type": "public", "client_id": "client_Hg6CknNkYlMgN190", "client_secret": null,
 "redirect_uris": ["https://cardio.example/callback"], "purpose": "cardiology follow-up", "status": "active", …}
```

Usa `public` per app mobile e browser, che non possono mantenere un segreto e si basano su PKCE. Usa `confidential` per un server; il suo `client_secret` viene mostrato una sola volta. Il nome, lo scopo e il link alla privacy sono ciò che la persona vede nella schermata di consenso.

## Passaggio 3: inviare la persona alla schermata di consenso

Crea una coppia PKCE. Il verificatore rimane con te; solo il suo hash viaggia:

```bash
VERIFIER=$(openssl rand -base64 64 | tr -d '=+/\n' | cut -c1-64)
CHALLENGE=$(printf %s "$VERIFIER" | openssl dgst -sha256 -binary | openssl base64 | tr '+/' '-_' | tr -d '=')
```

Quindi apri questo indirizzo nel browser della persona (interruzioni di riga aggiunte per la lettura):

```
https://platform.anpheros.com/oauth/authorize?response_type=code
  &client_id=client_Hg6CknNkYlMgN190
  &redirect_uri=https://cardio.example/callback
  &scope=openid fhirUser patient/Observation.rs?category=laboratory patient/Condition.rs offline_access
  &state=8c1e…               ← a random value you check on return
  &code_challenge=$CHALLENGE&code_challenge_method=S256
  &purpose=treatment&lang=en
```

Chiedi il minimo necessario. Questa applicazione legge i risultati di laboratorio e le diagnosi, nient'altro. `offline_access` fornisce un token di aggiornamento, in modo che la persona non debba approvare nuovamente ogni 30 minuti.

La persona accede ad Anpheros, legge la richiesta in linguaggio chiaro, sceglie quale record condividere (il proprio, quello di un familiare di cui si prende cura, o quello creato dalla tua app per loro) e per quanto tempo dura l'accesso, quindi consente o nega. Torna al tuo URI di reindirizzamento:

```
https://cardio.example/callback?code=…&state=8c1e…
```

Verifica che `state` sia il valore che hai inviato prima di utilizzare il codice.

## Fase 4: Scambiare il codice per i token

```bash
curl -X POST https://platform.anpheros.com/oauth/token \
  -d grant_type=authorization_code -d client_id=client_Hg6CknNkYlMgN190 \
  -d code=$CODE -d code_verifier=$VERIFIER -d redirect_uri=https://cardio.example/callback
```

```json
{"access_token": "at_…", "token_type": "Bearer", "expires_in": 1800,
 "scope": "patient/Observation.rs?category=laboratory patient/Condition.rs openid fhirUser offline_access",
 "patient": "82bfd321-6a4d-4aea-943a-a62f4d81d419", "grant_id": "grant_…",
 "id_token": "eyJ…", "refresh_token": "rt_…"}
```

- `scope` elenca ciò che è stato concesso. Mantenerlo con i token e mostrare solo le funzionalità che copre.
- `patient` è l'ID del record per la tua applicazione. È pairwise: un'altra applicazione vede la stessa persona con un ID diverso.
- `id_token` è un token OpenID Connect il cui claim `fhirUser` nomina la risorsa paziente.
- Il codice funziona una sola volta e solo con il `code_verifier` corrispondente.

## Passo 5: chiamare l'API all'interno degli scope

```bash
curl "https://platform.anpheros.com/fhir/R4/Observation?patient=$PATIENT&category=laboratory" -H "Authorization: Bearer $ACCESS_TOKEN"
```

I risultati di laboratorio arrivano come al solito. Chiedi qualcosa al di fuori della concessione, come i farmaci:

```bash
curl "https://platform.anpheros.com/fhir/R4/MedicationStatement?patient=$PATIENT" -H "Authorization: Bearer $ACCESS_TOKEN"
```

```json
{"resourceType": "OperationOutcome", "issue": [{"severity": "error", "code": "forbidden",
  "diagnostics": "The consent behind this token does not allow 's' on MedicationStatement."}]}
```

Questo è un `403`. Anche le ricerche all'interno della concessione vengono filtrate: con `Observation.rs?category=laboratory`, una ricerca di tutte le osservazioni restituisce solo quelle di laboratorio. Qualsiasi altro paziente non esiste per questo token (`404`). La vista REST (`/v1`) e l'[API di contesto](https://developers.anpheros.com/it/guides/llm-healthcare-data) applicano gli stessi scope.

## Step 6: refresh

I token di accesso durano 30 minuti. I token di refresh durano 30 giorni e ruotano ad ogni utilizzo:

```bash
curl -X POST https://platform.anpheros.com/oauth/token \
  -d grant_type=refresh_token -d client_id=client_Hg6CknNkYlMgN190 -d refresh_token=$REFRESH_TOKEN
```

Ottieni un nuovo token di accesso e un nuovo token di refresh. Memorizza subito quello nuovo. Il riutilizzo di un vecchio token di refresh viene trattato come un furto: fallisce con `400` e revoca l'intera concessione.

## Passaggio 7: revoca

La persona può revocare il tuo accesso da Anpheros in qualsiasi momento, e tu puoi revocarlo autonomamente, ad esempio quando si disconnettono nella tua app:

```bash
curl -X POST https://platform.anpheros.com/oauth/revoke -d token=$REFRESH_TOKEN -d client_id=client_Hg6CknNkYlMgN190
```

Da quel momento in poi, ogni chiamata con quella concessione risponderà `401`. Gestiscilo mostrando alla persona che la connessione è terminata e offrendoti di riconnetterti. Iscriviti al [webhook](https://developers.anpheros.com/it/guides/webhooks) `consent.revoked` per scoprirlo senza attendere una chiamata fallita.

## Con gli SDK

I [SDK TypeScript e Dart](https://developers.anpheros.com/it/guides/sdks) eseguono i passaggi da 3 a 6 per te: `OAuthFlow.authorizeUrl` con una coppia PKCE generata, `exchange` al callback e refresh automatico con rotazione. Esempi completi: [Come creare un'app sanitaria AI con un backend FHIR](https://developers.anpheros.com/it/guides/build-ai-healthcare-app) (TypeScript) e [Come creare un'app sanitaria con Flutter](https://developers.anpheros.com/it/guides/healthcare-app-flutter) (Dart).

## Cosa implementa Anpheros

| Parte di SMART | In Anpheros |
|---|---|
| Discovery | `/.well-known/smart-configuration` sulla base FHIR, con gli endpoint, gli scope e i metodi PKCE supportati |
| Launch | standalone launch (l'applicazione si avvia, quindi richiede l'accesso); EHR launch dall'interno di un sistema clinico non è offerto |
| Authorisation | OAuth 2.1 con PKCE richiesto, flusso di autorizzazione tramite codice |
| Scopes | scope paziente SMART v2, `patient/<Resource>.<cruds>` con filtri per categoria, più `openid` e `fhirUser` |
| Identity | un OpenID Connect `id_token` che nomina il paziente come risorsa FHIR |
| Consent | una schermata di consenso ospitata nella lingua del paziente, con la durata scelta dal paziente, rispecchiata come un FHIR `Consent` |
| Tokens | token di accesso da 30 minuti, token di refresh rotanti da 30 giorni legati al consenso, revoca |
| Conformance | la capability statement dichiara il servizio di sicurezza SMART; il gruppo "Standalone Launch" del kit di test Inferno SMART App Launch STU2 supera 22 test su 22 (esecuzione del 28 settembre 2026); gli altri gruppi e kit di test Inferno non sono stati eseguiti |

La scrittura funziona allo stesso modo: scrivere scope (`patient/Observation.c`, `.u`, `.d`) consente alla tua applicazione di creare, aggiornare o eliminare all'interno del record. Tutto ciò che viene scritto porta la tua applicazione come autore, i tentativi con una chiave di idempotenza non duplicano mai una misurazione e le eliminazioni sono "soft" e mantengono la cronologia ([Medical data API](https://developers.anpheros.com/it/guides/medical-data-api)).

## Cosa non è ancora disponibile

- EHR launch (l'applicazione aperta dall'interno di un sistema ospedaliero con un contesto di lancio).
- `system/` scope per servizi backend; le organizzazioni utilizzano invece API key.
- Bulk Data export (`$export`); `$everything` su un paziente è disponibile.

Questi sono elencati con il resto in [Versioning e deprecazione](https://developers.anpheros.com/it/guides/versioning), e la capability statement è sempre la fonte autorevole.

## Domande frequenti

### Cos'è SMART on FHIR?
Uno standard aperto, basato su OAuth 2.0/2.1 e OpenID Connect, che definisce come un'applicazione richiede l'accesso a un record FHIR, quali ambiti descrivono tale accesso e come il server pubblicizza i propri endpoint. Qualsiasi libreria client compatibile con SMART può utilizzare qualsiasi server compatibile con SMART.

### Ho bisogno di PKCE?
Sì. Anpheros richiede PKCE con `S256` per ogni flusso di codice di autorizzazione, sia per client pubblici che confidenziali. Impedisce che un codice di autorizzazione intercettato venga utilizzato da chiunque altro.

### Cosa succede se la persona dice di no?
Vengono reindirizzati al tuo URI di reindirizzamento con `error=access_denied` e il tuo `state`, e nessun codice. Spiega di cosa ha bisogno la funzionalità e lascia che riprovino; le chiamate al di fuori di una concessione rispondono sempre `403`.

### Un genitore può dare il consenso per un bambino?
Sì. Nella schermata di consenso una persona può scegliere un record a cui tiene, come quello di un bambino, se è collegato al proprio account. La concessione si applica solo a quel record.

## Correlati

- [Autenticazione e OAuth](https://developers.anpheros.com/it/guides/authentication): chiavi API, token e durate in dettaglio
- [API Sanitaria con consenso del paziente](https://developers.anpheros.com/it/guides/healthcare-api-patient-consent): come il consenso modifica la progettazione della tua applicazione
- [Modello di consenso e accesso](https://developers.anpheros.com/it/guides/consent)
- [Piattaforma FHIR](https://developers.anpheros.com/it/guides/fhir)
- [Creare un'app sanitaria](https://developers.anpheros.com/it/guides/build-a-healthcare-app)
