DevPortalPagoPA



Tabella dei contenuti

Come richiedere un voucher DPoP per le API di un erogatore (base)

Questo tutorial spiega come richiedere un voucher che utilizza Demonstrating Proof‑of‑Possession (DPoP) – lo standard IETF (RFC 9449) che rende un voucher (token JWT) inutilizzabile se sottratto, perché vincolato a una chiave pubblica posseduta dal chiamante. Per maggiori dettagli, si veda l'approfondimento.
Maggiori informazioni su questa implementazione nella sezione dedicata.

Il flusso in breve

In sostanza, il processo end-to-end richiede sette passaggi:
  1. il fruitore genera la client assertion standard; la firma con la chiave privata la cui pubblica è depositata sul proprio client su PDND Interoperabilità;
  2. il fruitore costruisce la DPoP destinata al server autorizzativo di PDND; la firma con una seconda chiave privata la cui pubblica sarà inserita nell'intestazione della DPoP, nel campo jwk;
  3. il fruitore chiede il voucher al server autorizzativo di PDND, aggiungendo l'header DPoP;
  4. il server autorizzativo di PDND effettua le verifiche necessarie. In caso di esito positivo, restituisce un voucher di tipo DPoP;
  5. il fruitore costruisce una seconda DPoP, questa volta destinata al resource server, ossia l'API dell'e-service dell'erogatore; la firma con la stessa chiava privata della DPoP al punto 2, mettendo anche qusta volta la chiave pubblica corrispondente nell'intestazione della DPoP, nel campo jwk;
  6. il fruitore fa una richiesta verso l'e-service dell'erogatore; inserisce sia il voucher rilasciato da PDND Interoperabilità nell'header Authorization, sia la DPoP generata al punto precedente nell'header DPoP;
  7. l'erogatore effettua le verifiche necessarie. In caso di esito positivo, elabora la richiesta del fruitore.

Prerequisiti

Si assume che il fruitore abbia:
  • creato un client di tipo e-service (vedi tutorial);
  • generato almeno un set di materiale crittografico e caricato la relativa chiave pubblica su PDND Interoperabilità all'interno del client (vedi tutorial);
  • associato il client alla finalità per la quale vuole ottenere o inviare dati all'erogatore (vedi tutorial).

Step 1 - Generazione della client assertion

Il primo passo è costruire una client assertion valida. La client assertion è composta da un header e un payload, contenenti i seguenti campi.
Header:
Nome campoSignificato
kidl'id della chiave che si usa per firmare l'asserzione, reperibile su PDND Interoperabilità
algl'algoritmo usato per firmare il JWT (per ora, sempre RS256)
typil tipo di oggetto che si sta inviando (sempre JWT)
Payload:
Nome campoSignificato
issl'issuer, in questo caso il clientId
subil subject, in questo caso sempre il clientId
audl'audience, reperibile su PDND Interoperabilità
jtiil JWT ID, un id unico random assegnato da chi vuole creare il token, si usa per tracciare il token stesso. Deve essere cura del chiamante assicurarsi che l'id di questo token sia unico per quanto riguarda la client assertion
iatl'issued at, il timestamp riportante data e ora in cui viene creato il token, espresso in UNIX epoch (valore numerico, non stringa)
expl'expiration, il timestamp riportante data e ora di scadenza del token, espresso in UNIX epoch (valore numerico, non stringa)
purposeIdl'id della singola finalità per la quale si vuole ottenere un voucher, disponibile sul back office
A titolo esemplificativo, di seguito un esempio di contenuto di client assertion deserializzata, in modo da evidenziarne il contenuto.
Header:
1{
2  "alg": "RS256",
3  "kid": "2MJFa7aSSveFte8ULX9U-MaaygcoL5fBIJDTXBdba64",
4  "typ": "jwt"
5}
6
Payload:
1{
2  "iss": "8e9f24ca-78f5-4c69-9e4f-0efbeac7bb2b", 
3  "sub": "8e9f24ca-78f5-4c69-9e4f-0efbeac7bb2b",
4  "aud": "auth.interop.pagopa.it/client-assertion",
5  "jti": "23387ac1-c192-4573-8350-207a4213d4be",
6  "iat": 1616170068,
7  "exp": 1616170668,
8  "purposeId": "34f1624b-91cb-4b05-b8c0-cad208a30222"
9}
10
Dopo aver costruito una client assertion valida, questa deve essere firmata con la propria chiave privata (che deve essere l'omologa della chiave pubblica depositata sul client su PDND Interoperabilità).
A scopo esemplificativo, è stato pubblicato uno script Python per dimostrare come eseguire l'operazione. Tutte le istruzioni sono disponibili nel back office, all'interno del proprio client.
È inoltre disponibile una funzione per verificare la validità della propria client assertion ed evidenziare eventuali errori. Lo strumento è disponibile nel back office su Tool per lo sviluppo > Debug client assertion.

Step 2 - Generazione della prima DPoP

Il fruitore procede quindi alla costruzione della DPoP destinata al server autorizzativo di PDND, vale a dire un JWT con
Header:
1{
2  "typ": "dpop+jwt",
3  "alg": "ES256",
4  "jwk": "{CHIAVE_PUBBLICA_CHIAMANTE}"
5}
6
Payload:
1{
2  "htm": "POST",
3  "htu": "https://auth.interop.pagopa.it/token.oauth2",
4  "iat": 1747406361,
5  "jti": "b60203a7-6f31-4d08-a3d1-f69ba308eee0"
6}
7
Ecco nel dettaglio i campi sopra indicati:
Nome campoSignificato
typdeve essere impostato a dpop+jwt
algindica l'algoritmo usato per la firma della DPoP. L'algoritmo consigliato è ES256
jwkla chiave pubblica in formato JWK corrispondente alla chiave privata utilizzata per firmare la DPoP
htmindica il metodo HTTP che si sta invocando. Per l'ottenimento di un voucher da PDND Interoperabilità, il metodo è POST
htuindica l'URL che si sta invocando. Per l'ottenimento di un voucher da PDND Interoperabilità in ambiente di produzione è https://auth.interop.pagopa.it/token.oauth2 (per gli ambienti di attestazione e collaudo va inserita quella specifica)
iatl'issued at, il timestamp riportante data e ora in cui viene creata la DPoP, espresso in UNIX epoch (valore numerico, non stringa)
jtiidentificativo univoco della DPoP. Deve essere cura del fruitore assicurarsi che l'id di questo token sia unico e non venga riutilizzato

Step 3 - Richiedere il voucher al server autorizzativo

Il terzo passaggio è chiamare il server autorizzativo di PDND Interoperabilità con la client assertion firmata per ottenerne in cambio un voucher spendibile presso le API di PDND Interoperabilità.
Nell'header della richiesta dovrà inserire un header DPoP, che conterrà la DPoP generata al passaggio precedente:
DPoP: <DPoP_proof>
L'URL dell'endpoint alla quale si trova il server autorizzativo cambia in funzione dell'ambiente in cui ci si trova e sarà chiaramente visibile sull'interfaccia all'interno del back office.
L'endpoint andrà chiamato con alcuni parametri nel body:
Nome campoSignificato
client_iddi nuovo il clientId usato nell'assertion
client_assertionil contenuto dell'asserzione firmata nel primo passaggio
client_assertion_typeil formato della client assertion, come indicato in RFC (sempre urn:ietf:params:oauth:client-assertion-type:jwt-bearer)
grant_typela tipologia di flusso utilizzato, come indicato in RFC (sempre client_credentials)

Step 4 - Il server autorizzativo verifica, e rilascia il voucher

Il server autorizzativo di PDND Interoperabilità effettua le verifiche necessarie, in particolare:
  • verifica la client-assertion secondo i controlli già previsti;
  • verifica la firma della DPoP utilizzando la chiave pubblica indicata nel campo jwk contenuto nel header;
  • controlla che i campi htm e htu corrispondano ai valori attesi per la richiesta in corso;
  • considera temporalmente valida una proof presentata entro 60 secondi dalla data di emissione della proof stessa (iat);
  • verifica che il valore del campo jti non sia già stato utilizzato per un'altra chiamata verso il server autorizzativo di PDND Interoperabilità.
Il server autorizzativo di PDND Interoperabilità, validata la DPoP, restituisce un voucher di tipo DPoP (campo token_type) firmato come JWT con header di tipo "typ": "at+jwt" e contenente un claim cnf.jkt.
La risposta che il server autorizzativo di PDND Interoperabilità restituisce è la seguente:
1{
2  "access_token": "eyJ0eXAiOiJhdCtqd3QiLC...",
3  "expires_in": 600,
4  "token_type": "DPoP"
5}
6
Se decodifichiamo il campo dedicato all'access_token, troviamo
Header:
1{
2  "typ": "dpop+jwt",
3  "alg": "RS256",
4  "use": "sig",
5  "kid": "{KID_CHIAVE_PDND}"
6}
7
Payload:
1{
2  "iss": "interop.pagopa.it", 
3  "nbf": 1747408537,
4  "iat": 1747408537,
5  "exp": 1747409537,
6  "jti": "12297ac1-c192-4573-8350-207a4213e5ac",
7  "aud": "https://eservice.pa.it/api/v1",
8  "sub": "9b361d49-33f4-4f1e-a88b-4e12661f2309",
9  "client_id": "9b361d49-33f4-4f1e-a88b-4e12661f2309",
10  "purposeId": "1b361d49-33f4-4f1e-a88b-4e12661f2300",
11  "producerId" : "0e9e2dab-2e93-4f24-ba59-38d9f11198ca",
12  "consumerId" : "69e2865e-65ab-4e48-a638-2037a9ee2ee7",
13  "eserviceId" : "b8c6d7ad-93fc-4eaf-9018-3cd8bf98163f",
14  "descriptorId": "9525a54b-9157-4b46-8976-ec66f20b7d7e",
15  "cnf": {
16    "jkt" : "L5TP6x6ved3p_jmIAtCiHMcNJeRrGWAusNnQkTTrnLY"
17  }
18}
19
dove il campo cnf.jkt contiene il thumbprint della chiave pubblica in formato JWK (RFC 7638) utilizzata nella DPoP inviata dal fruitore (client) verso PDND Interoperabilità (server autorizzativo).

Step 5 - Il fruitore costruisce una seconda DPoP

Il fruitore costruisce una seconda DPoP, che questa volta è destinata alle API dell'e-service dell'erogatore. Questa seconda DPoP è simile a quella prodotta nel secondo passaggio, con due differenze:
  • i campi htm e htu devono essere valorizzati con la risorsa che verrà chiamata sul server dell'erogatore indicata nel file di interfaccia API, invece che fare riferimento al server autorizzativo di PDND Interoperabilità;
  • va inserito un altro campo, ath .
Il campo ath contiene l'hash del voucher rilasciato da PDND Interoperabilità. Questo hash è ottenuto usando SHA256 e deve essere codificato in Base64URL, con la seguente formula:
1BASE64URL(SHA-256(access_token_bytes))
2

Step 6 - Richiedere i dati all'ergoatore

Il voucher andrà inserito nell'header di tutte le chiamate successive verso le API dell'erogatore. Andrà inserito come header, come segue:
1Authorization: DPoP <voucher_rilasciato_da_PDND>
2
Inoltre, il fruitore deve inserire anche un altro header, in particolare:
DPoP: <DPoP_proof_generata_al_passaggio_precedente>

Step 7 - Attendere le verifiche dell'erogatore

L'erogatore effettua tutte le verifiche necessarie. Se tutto è in ordine, elabora la richiesta del fruitore, restituendogli i dati richiesti in caso di e-service che eroga dati, oppure accettando i dati dal fruitore in caso di e-service che riceve dati.
Per consultare le verifiche consigliate agli erogatori, si veda la sezione dedicata.

Hai bisogno di aiuto?

Apri un ticket utilizzando l’apposita funzione all’interno della tua Area Riservata

Dicci cosa ne pensi

Per segnalare problemi o dare feedback, puoi aprire una segnalazione su Github