# Popolare un form con dati provenienti da API

{% hint style="warning" %}
Per utilizzare endpoint API esterni è necessario fare inizialmente riferimento a OpenCity Italia, in modo tale da sbloccare il CSP (Content Security Policy) nel caso in cui l'Ente intenda utilizzare [API non protette da autenticazione](#api-senza-autenticazione) sia [API protette da autenticazione](#api-protette-da-autenticazione).

La funzione può essere utilizzata per recuperare, all'interno del modulo, [dati provenienti da un'altra istanza](https://docs.opencityitalia.it/guida-alla-creazione-dei-servizi-digitali/creare-un-servizio/le-funzioni/configurare-servizi-a-piu-fasi).
{% endhint %}

Come admin puoi configurare alcuni campi (es. [Select](https://docs.opencityitalia.it/guida-alla-creazione-dei-servizi-digitali/creare-un-servizio/i-componenti/la-select) o [Textfield](https://docs.opencityitalia.it/guida-alla-creazione-dei-servizi-digitali/creare-un-servizio/i-componenti/il-textfield)) in modo tale che vengano compilati con dati presi dalle API.

## Configurare una *select* con dati presi dalle API

Nella sezione "Data" del componente, configura la voce "Data source type" con l'opzione URL

<figure><img src="https://4252442743-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrdV0mwA7iy2c3I7wu5BX%2Fuploads%2FgJIvIa8RbnSxNX7N5QDV%2Fimage.png?alt=media&#x26;token=17b5da5c-fa69-4957-8b83-5396a1de2967" alt=""><figcaption></figcaption></figure>

Successivamente inserisci l'endpoin API da utilizzare alla voce "Data source url"

<figure><img src="https://4252442743-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrdV0mwA7iy2c3I7wu5BX%2Fuploads%2FNsyoBC4g5SiMdwMNjeEZ%2Fimage.png?alt=media&#x26;token=e8b22f7a-d120-4d09-8ff3-54fe1d60c4b1" alt=""><figcaption></figcaption></figure>

Alla voce "Storage type" indica il dato da riportare nella select (è consigliabile usare l'opzione "autotype", in modo da predere tutto l'oggetto restituito dall'API)

<figure><img src="https://4252442743-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrdV0mwA7iy2c3I7wu5BX%2Fuploads%2Ftyq9roe228ymFEwuDAKL%2Fimage.png?alt=media&#x26;token=c3eb5e61-3723-4081-b13d-cc3f825ee7cf" alt=""><figcaption></figcaption></figure>

Infine, scegli il valore da mostrare alla voce "Item template".

<figure><img src="https://4252442743-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrdV0mwA7iy2c3I7wu5BX%2Fuploads%2Fb10ZtTrdoQv5UkRfXygR%2Fimage.png?alt=media&#x26;token=4afea785-bcd8-4c70-82b7-8da959c9aaf6" alt=""><figcaption></figcaption></figure>

È consigliabile compilare anche il campo "Limit" e indicare un numero massimo di item da visualizzare.

Più alto è il valore indicato più tempo la select ci metterà a caricare gli item; è quindi consigliabile indicare un massimo di 50

<figure><img src="https://4252442743-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrdV0mwA7iy2c3I7wu5BX%2Fuploads%2FblYYwhjRMjtp0r9WQLAY%2Fimage.png?alt=media&#x26;token=b7a520e1-43a4-4519-b1b2-6c2954b0c015" alt=""><figcaption></figcaption></figure>

## Configurare un *text field* con i dati presi da API

Nella sezione "Data" del componente, compila la voce "Calculated value" con un codice Json contentente l'URL API:

<div data-full-width="true"><figure><img src="https://4252442743-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrdV0mwA7iy2c3I7wu5BX%2Fuploads%2FtNaK1l2IQXSFVDBdgix8%2Fimage.png?alt=media&#x26;token=4eb87e58-6f2e-4ee5-9b3e-2790a73e5396" alt=""><figcaption></figcaption></figure> <figure><img src="https://4252442743-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrdV0mwA7iy2c3I7wu5BX%2Fuploads%2FJoE5ovKFBqfVjEm0kAnk%2FScreenshot%20(17).png?alt=media&#x26;token=09c1d760-381d-456c-a302-2db2a3d89e5f" alt=""><figcaption></figcaption></figure></div>

Qui trovi un codice di esempio in cui vengono richiamati i dati di un'utenza TARI basandoci sul codice fiscale del richiedente

```json
async function get_data(url, token) {
    try {
        const response = await fetch(url, {
            method: 'GET', 
            headers: {
                'Authorization': `Bearer ${token}`,
                'Content-Type': 'application/json'
            }
        })

        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`)
        }

        const data = await response.json() // Parse JSON response
        instance.setValue(data.contract_code)
    } catch (error) {
        instance.setValue("ERRORE")
        console.error('Error fetching data:', error)
        throw error // Optionally re-throw the error for further handling
    }
}

if (!value && data?.applicant?.data.fiscal_code?.data?.fiscal_code && data?.token) {
  get_data(`https://govway.comune.bugliano.pi.it/govway/Ente/TARI/v1/getContractCode.php?cf=${data.applicant.data.fiscal_code.data.fiscal_code}`, data.token)
}
```

## API non protette da autenticazione

Per popolare un form, puoi utilizzare API non protette da autenticazione.

In questo caso, oltre allo sblocco di CSP da parte di OpenCity Italia, è necessario che le API utilizzate siano **pubbliche e raggiungibili**.

## API protette da autenticazione

Dataset e micro servizi esterni alla piattaforma possono essere facilmente integrati tramite il flusso di autenticazione basato su **JWT** (JSON Web Token) e **JWKS** (JSON Web Key Set)

<figure><img src="https://docs.opencityitalia.it/~gitbook/image?url=https%3A%2F%2F2402436129-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FNwAiDeLoMPCkkp1BdSbI%252Fuploads%252Fph2eSnbsWYF23XlY9npn%252FSchermata%25202024-06-13%2520alle%252013.57.11.png%3Falt%3Dmedia%26token%3Df3127994-bc59-4ed9-aa70-353b743c20c9&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=3f952145&#x26;sv=2" alt=""><figcaption><p>Diagramma del flusso di autenticazione con JWT e JWKS</p></figcaption></figure>

Questo flusso di autenticazione prevede alcuni passaggi chiave e interazioni tra:

* **client** (browser dell'utente)
* **area personale**
* **micro servizio esterno**

Di seguito il processo punto per punto:

### **1. Il client richiede il token**

Il client invia una richiesta all'area personale per ottenere un JWT, spesso includendo le credenziali dell'utente o altre forme di autorizzazione.

Come descritto nella sezione [Single Sign-On](https://docs.opencityitalia.it/v/developers/integrazioni/single-sign-on) è possibile per un utente autenticato richiedere un token di autenticazione per la propria sessione.

Questa operazione può essere effettuata facendo una chiamata alle API:

{% embed url="<https://servizi.comune.bugliano.pi.it/lang/api/session-auth>" %}
API per ottenere il token JWT come utente loggato
{% endembed %}

oppure come utente non autenticato effettuando una chiamata POST alle API

{% embed url="<https://servizi.comune.bugliano.pi.it/lang/api/authservizi.comune.bugliano.pi.it>" %}
API per ottenere il token JWT passando le credenziali
{% endembed %}

```sh
curl --request POST \
  --url https://servizi.comune.bugliano.pi.it/lang/api/auth \
  --header 'Content-Type: application/json' \
  --data '{
	"username": "username",
	"password": "password"
}'
```

### **2. L'area personale rilascia il token**

L'area personale autentica il client, genera un JWT e lo firma con una chiave privata.

Il token viene quindi restituito al client.

{% code overflow="wrap" %}

```json
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6InNkYy1xYSJ9.eyJpYXQiO.c2VybmFtZSI6ImFkbWluIiwiaWQiOiI2ZmZkZWRkZi04NmZhLTRjYmEtODUzNC05YTBlNjZmZTNlYmYiLCJ0ZW[...]5hbnRfaWQiOiI2MGUzNWYwMi0xNTA5LTQwOGMtYjEwMS0zYjFhMjgxMDkzMjkifQ.lFe0MR-LAj[...]RjoVvqwk3OX23T642ETu8PUy8sFaVRf1oM1qAnPhLEpnOcrIQY65mpKw6mrJ1rzZM5OVvEeOc4xxmtgcBOfMEBJo_Dw1pMfZHOv2S1S50Zr9XNxk0LcfWjXGdC7wy81eF7UuF-3cX9W"
}
```

{% endcode %}

### **3. Il client richiede la risorsa al micro servizio esterno:**

Il client invia una richiesta al **micro servizio esterno** per accedere a una risorsa protetta, includendo il JWT nell'intestazione Authorization.

```sh
curl --request GET \
  --url '{Url API micro servizio esterno}' \
  --header 'Authorization: Bearer {JWT Token}'
```

### **4. Il micro servizio esterno convalida il token**

Per verificare la validità del token il micro servizio esterno **deve:**

* Estrarre il JWT dalla richiesta
* Recuperare il JWKS dall'area personale, il JWKS contiene le chiavi pubbliche necessarie per verificare la firma del JWT.
* Verificare la firma del JWT e convalidare le sue richieste

{% hint style="info" %}
L'area personale espone il JWKS all'indirizzo:&#x20;

[`https://api.stanzadelcittadino.it/.well-known/jwks.json`](https://api.stanzadelcittadino.it/.well-known/jwks.json)
{% endhint %}

### **5. Accesso concesso/negato:**

In base alla validità del JWT il micro servizio esterno concede o nega l'accesso alla risorsa richiesta.

Oltre alla validità del token si possono verificare le affermazioni in esso contenute.

Il payload del token prodotto dall'area personale presenta delle informazioni utili a capire se quello specifico utente oltre ad avere un token valido **ha i permessi** per ottenere la risorsa richiesta.

Di seguito un esempio di payload del token

```json
{
  "iat": 1718278670,
  "exp": 1719142670,
  "roles": [
    "ROLE_CPS_USER",
    "ROLE_USER"
  ],
  "username": "BNRMHL75C06G702B",
  "id": "5b00796e-ef10-4c98-b9f5-b0f7ffd7a17d",
  "tenant_id": "60e35f02-1509-408c-b101-3b1a28109329"
}
```

## Un esempio pratico

Qui trovi un esempio dettagliato di un'integrazione di un modulo Opencity Italia che attinge a una API protetta mediante l'API gateway opensource GovWay di Link.it

{% embed url="<https://docs.opencityitalia.it/developers/integrazioni/integrazione-di-un-servizio-di-terze-parti-protetto-da-autenticazione/esempio-con-govway>" %}
