Vai al contenuto principale

DCQL spiegato: come un verificatore chiede a un wallet esattamente ciò che gli serve

Il Digital Credentials Query Language, DCQL, è il formato di query JSON che OpenID4VP utilizza all'interno di una richiesta di presentazione. Consente a una relying party di descrivere quali credenziali, e quali attributi al loro interno, desidera vedere, in un modo che qualsiasi wallet conforme può interpretare senza un'integrazione su misura.

Il problema che DCQL risolve

Un business wallet può contenere credenziali in diversi formati: una registrazione dell'impresa come SD-JWT VC, una qualifica professionale codificata come mdoc, una verifiable credential W3C di un progetto pilota precedente. Un verificatore che deve solo confermare un numero di registrazione e una ragione sociale non ha un modo portabile per chiedere esattamente questo tra formati diversi, se non accettando l'intera credenziale o scrivendo a mano una richiesta separata per ogni formato e per ogni fornitore di wallet.

DCQL colma questa lacuna sul lato della richiesta. È un unico oggetto JSON, incorporato nella richiesta di autorizzazione OpenID4VP, che definisce una o più credential query, ciascuna vincolata a un formato e a un insieme di percorsi di attributi. Il wallet valuta la query rispetto alle credenziali archiviate, individua quelle corrispondenti e solo allora chiede al titolare di approvare il rilascio di quegli attributi specifici. Il verificatore riceve una struttura prevedibile da elaborare, indipendentemente dal wallet usato dal titolare.

1. Verificatore

Invia una richiesta OpenID4VP con una dcql_query

2. Wallet

Confronta la query con le credenziali archiviate

3. Titolare

Approva il rilascio dei soli attributi richiesti

4. Verificatore

Riceve una presentazione per ogni id di credential query

La forma di una query DCQL

Una query DCQL è un unico oggetto JSON con un array credentials e, facoltativamente, un array credential_sets. Ogni voce di credentials è una credential query. I campi contrassegnati con M sono obbligatori in quella query.

dcql_query

credentials[ ]

Una credential query per ogni credenziale necessaria

id + format

Quale credenziale, in quale formato

meta

Filtro sul tipo, ad esempio vct_values

claims[ ]

Percorsi degli attributi da rivelare

claim_sets[ ]

Combinazioni di attributi accettabili

credential_sets[ ]

Facoltativo: quali combinazioni di credential query soddisfano la richiesta

CampoTipoObbligatorio
idstringM
formatenum: dc+sd-jwt | mso_mdoc | jwt_vc_json | ldp_vcM
metaoggetto, la forma dipende dal formato
claimsarray di claim query
claim_setsarray di array di id di attributi
trusted_authoritiesarray di oggetti con un tipo e dei valori

Ogni voce di claims è a sua volta un oggetto: un id usato per richiamarla da claim_sets, un path, cioè un array che individua l'attributo all'interno della credenziale (ad esempio ["legal_name"] per un attributo SD-JWT di primo livello o ["org", "registration_number"] per uno annidato), e facoltativamente values, un elenco di valori a cui l'attributo deve corrispondere.

Esempio pratico: verifica della registrazione di un'impresa

Registrazione dell'impresa

dc+sd-jwt

Il verificatore dice: ecco cosa voglio ricevere

  • ✓ Numero di registrazionereg_nopath: ["registration_number"]
  • ✓ Ragione socialelegal_namepath: ["legal_name"]
  • ✓ Paese di registrazionereg_countrypath: ["registration_country"]
{
  "credentials": [
    {
      "id": "company_registration",
      "format": "dc+sd-jwt",
      "meta": {
        "vct_values": ["urn:eudi:business:company-registration:1"]
      },
      "claims": [
        { "id": "reg_no", "path": ["registration_number"] },
        { "id": "legal_name", "path": ["legal_name"] },
        { "id": "reg_country", "path": ["registration_country"] }
      ]
    }
  ]
}

Esempio di risposta del wallet

Il wallet risponde con un oggetto vp_token le cui chiavi sono gli id delle credential query. Ogni valore è un array di presentazioni. Per dc+sd-jwt una presentazione è composta dal JWT firmato dall'emittente, da una disclosure per ogni attributo rilasciato e da un key binding JWT che la lega al nonce e al client di questa richiesta.

Cosa invia il wallet

{
  "vp_token": {
    "company_registration": [
      "<issuer-signed JWT>~<disclosure: registration_number>~<disclosure: legal_name>~<disclosure: registration_country>~<key binding JWT>"
    ]
  }
}

Attributi visibili al verificatore dopo la validazione

{
  "vct": "urn:eudi:business:company-registration:1",
  "registration_number": "12345678",
  "legal_name": "Example Logistics B.V.",
  "registration_country": "NL"
}

Prevedere un'alternativa: claim_sets

claim_sets elenca gruppi di id di attributi in ordine di preferenza. Il wallet restituisce il primo gruppo che può soddisfare interamente con ciò che il titolare possiede davvero, evitando al verificatore di inviare due richieste separate per il caso preciso e per quello alternativo.

Esempio pratico: numero di registrazione, oppure solo la ragione sociale

1. Preferito

reg_nolegal_name

Restituito se la credenziale contiene entrambi gli attributi

2. Alternativa

legal_name

Restituito solo se il primo set non può essere soddisfatto

{
  "credentials": [
    {
      "id": "company_registration",
      "format": "dc+sd-jwt",
      "meta": { "vct_values": ["urn:eudi:business:company-registration:1"] },
      "claims": [
        { "id": "reg_no", "path": ["registration_number"] },
        { "id": "legal_name", "path": ["legal_name"] }
      ],
      "claim_sets": [
        ["reg_no", "legal_name"],
        ["legal_name"]
      ]
    }
  ]
}

Qui il verificatore preferisce il numero di registrazione insieme alla ragione sociale, ma accetta la sola ragione sociale se la credenziale del titolare non contiene l'attributo del numero di registrazione.

Esempio di risposta: è stata usata l'alternativa

Cosa invia il wallet

{
  "vp_token": {
    "company_registration": [
      "<issuer-signed JWT>~<disclosure: legal_name>~<key binding JWT>"
    ]
  }
}

Attributi visibili al verificatore dopo la validazione

{
  "vct": "urn:eudi:business:company-registration:1",
  "legal_name": "Example Logistics B.V."
}

La credenziale del titolare non ha un numero di registrazione, quindi il wallet ha soddisfatto il secondo claim set e rilasciato una sola disclosure. La risposta non indica quale set è stato usato: il verificatore lo deduce dagli attributi che riceve.

Combinare credenziali: credential_sets

credential_sets opera un livello sopra claim_sets. Ogni voce elenca delle options, dove ogni opzione è un gruppo di id di credential query. Il wallet deve soddisfare un'opzione per ogni voce obbligatoria, il che offre al verificatore una logica AND e OR tra credenziali in un'unica richiesta.

Obbligatorio

Registrazione dell'impresa

AND

Uno tra

Partita IVA

OR

Uno tra

Attestazione del conto bancario

"credential_sets": [
  { "options": [["company_registration"]] },
  { "options": [["vat_registration"], ["bank_account"]] }
]

Esempio di risposta: registrazione più conto bancario

Cosa invia il wallet

{
  "vp_token": {
    "company_registration": [
      "<issuer-signed JWT>~<disclosures>~<key binding JWT>"
    ],
    "bank_account": [
      "<issuer-signed JWT>~<disclosures>~<key binding JWT>"
    ]
  }
}

Attributi visibili al verificatore dopo la validazione

{
  "company_registration": {
    "vct": "urn:eudi:business:company-registration:1",
    "registration_number": "12345678",
    "legal_name": "Example Logistics B.V."
  },
  "bank_account": {
    "vct": "urn:eudi:business:bank-account:1",
    "iban": "NL91ABNA0417164300",
    "account_holder": "Example Logistics B.V."
  }
}

Il titolare non ha una credenziale di partita IVA, quindi il wallet ha scelto la seconda opzione del secondo set. Gli id di query non utilizzati, qui vat_registration, semplicemente non compaiono in vp_token.

Solo emittenti affidabili: trusted_authorities

trusted_authorities limita una credential query alle credenziali il cui emittente è garantito da un'autorità di cui il verificatore si fida. Ogni voce ha un tipo e un elenco di valori: aki per un authority key identifier, etsi_tl per una trusted list ETSI oppure openid_federation per un trust anchor di federazione. Il wallet propone solo le credenziali corrispondenti.

Esempio pratico: una registrazione da un emittente in lista

Il verificatore dice: solo da emittenti in questa lista di fiducia

type: etsi_tl

https://ec.europa.eu/tools/lotl/eu-lotl.xml

Credenziale di registrazione da un emittente in lista

l'emittente è nella lista di fiducia

✓ Corrisponde alla query

Credenziale di registrazione da un emittente non in lista

l'emittente non è nella lista di fiducia

✗ Non corrisponde, non proposta al titolare

{
  "credentials": [
    {
      "id": "company_registration",
      "format": "dc+sd-jwt",
      "meta": { "vct_values": ["urn:eudi:business:company-registration:1"] },
      "trusted_authorities": [
        {
          "type": "etsi_tl",
          "values": ["https://ec.europa.eu/tools/lotl/eu-lotl.xml"]
        }
      ],
      "claims": [
        { "id": "reg_no", "path": ["registration_number"] },
        { "id": "legal_name", "path": ["legal_name"] }
      ]
    }
  ]
}

Esempio di risposta: solo la credenziale dell'emittente in lista

Cosa invia il wallet

{
  "vp_token": {
    "company_registration": [
      "<issuer-signed JWT>~<disclosure: registration_number>~<disclosure: legal_name>~<key binding JWT>"
    ]
  }
}

Attributi visibili al verificatore dopo la validazione

{
  "vct": "urn:eudi:business:company-registration:1",
  "registration_number": "12345678",
  "legal_name": "Example Logistics B.V."
}

Il titolare aveva anche una credenziale di registrazione di un emittente non in lista, ma il wallet non l'ha proposta. trusted_authorities è un filtro per il wallet, non una garanzia: il verificatore controlla comunque in autonomia l'emittente rispetto alla lista di fiducia quando valida la presentazione.

Verificare un valore: claims.values

Una claim query può includere values, un elenco di stringhe, interi o booleani. Il wallet restituisce l'attributo solo se tipo e valore corrispondono esattamente a uno di essi, così un verificatore può controllare una condizione senza prima chiedere altro.

Esempio pratico: solo imprese registrate nei Paesi Bassi o in Belgio

Il verificatore dice: solo un'impresa registrata in uno di questi paesi

reg_countryvalues:"NL""BE"

Impresa olandese

registration_country: "NL"

✓ Corrisponde alla query

Impresa tedesca

registration_country: "DE"

✗ Non corrisponde, non proposta al titolare

{
  "credentials": [
    {
      "id": "company_registration",
      "format": "dc+sd-jwt",
      "meta": { "vct_values": ["urn:eudi:business:company-registration:1"] },
      "claims": [
        { "id": "legal_name", "path": ["legal_name"] },
        {
          "id": "reg_country",
          "path": ["registration_country"],
          "values": ["NL", "BE"]
        }
      ]
    }
  ]
}

Esempio di risposta: un'impresa olandese

Cosa invia il wallet

{
  "vp_token": {
    "company_registration": [
      "<issuer-signed JWT>~<disclosure: legal_name>~<disclosure: registration_country>~<key binding JWT>"
    ]
  }
}

Attributi visibili al verificatore dopo la validazione

{
  "vct": "urn:eudi:business:company-registration:1",
  "legal_name": "Example Logistics B.V.",
  "registration_country": "NL"
}

La credenziale di un'impresa tedesca ha registration_country "DE", quindi non soddisfa la query e il wallet non ha nulla da restituire. Il verificatore dovrebbe comunque controllare il valore negli attributi validati anziché affidarsi al filtro del wallet.

Vincoli specifici del formato in meta

SD-JWT VC: vct_values

Per dc+sd-jwt, meta.vct_values elenca gli identificatori di tipo di credenziale accettati dal verificatore. Una query corrisponde solo a una credenziale archiviata il cui vct è uno dei valori elencati, quindi un verificatore che si fida solo del tipo di credenziale di registrazione di un emittente elenca esattamente quell'identificatore.

mso_mdoc: doctype_value e namespace

Per mso_mdoc, meta.doctype_value fissa il DocType ISO 18013-5 e ogni percorso di attributo inizia con il namespace mdoc a cui appartiene l'attributo invece che con un semplice nome di campo, poiché mdoc raggruppa gli attributi per namespace anziché in un oggetto piatto.

A che punto è DCQL oggi

  • DCQL è definito all'interno della specifica OpenID4VP stessa, non in un documento separato, e fa parte della bozza da quando il meccanismo è stato introdotto per sostituire la precedente dipendenza da DIF Presentation Exchange nelle richieste OpenID4VP.
  • L'EUDI Wallet Architecture and Reference Framework indica OpenID4VP come protocollo di presentazione e, con esso, DCQL come meccanismo di query che relying party e wallet dell'ecosistema devono supportare.
  • Le implementazioni di riferimento di wallet e verificatori del programma EUDI Wallet Reference Implementation sono convergite su DCQL, quindi le nuove integrazioni di business wallet basate su OpenID4VP dovrebbero oggi presupporre DCQL, e non Presentation Exchange, come formato di query per le richieste di presentazione.

Termini correlati

Domande frequenti

In cosa DCQL differisce da DIF Presentation Exchange?

Entrambi descrivono ciò che un verificatore vuole da un wallet, ma DCQL è circoscritto a OpenID4VP ed è definito direttamente in quella specifica, mentre Presentation Exchange è una specifica DIF separata che copre anche altri protocolli. DCQL è volutamente più snello: non prevede gruppi di input descriptor né submission requirements ed esprime i vincoli specifici del formato, come il doctype di un mdoc o il tipo di una SD-JWT VC, direttamente nell'oggetto della query anziché tramite un filtro JSON Schema generico. L'ecosistema EUDI Wallet ha adottato DCQL come standard per le presentazioni OpenID4VP.

Una query DCQL può richiedere più di una credenziale?

Sì. L'array credentials può elencare diverse credential query, ciascuna con il proprio id. Un wallet che possiede corrispondenze per ogni voce restituisce una presentazione per ciascuna. L'oggetto facoltativo credential_sets permette inoltre di richiedere combinazioni specifiche, ad esempio accettare una credenziale di registrazione dell'impresa da sola oppure insieme a una dichiarazione UBO, senza interpellare il titolare due volte.

Quale problema risolve claim_sets all'interno di una singola credential query?

Una credenziale non contiene sempre tutti gli attributi che un verificatore vorrebbe. claim_sets elenca gruppi alternativi di id di attributi, ognuno dei quali basterebbe da solo a soddisfare la richiesta, in ordine dal più al meno preferito. Il wallet sceglie il primo gruppo che può soddisfare interamente con gli attributi effettivamente posseduti dal titolare, così un verificatore può chiedere un numero identificativo preciso quando disponibile e ripiegare su una verifica meno granulare, come un indicatore di maggiore età, senza inviare due richieste separate.

DCQL è specifico dell'EUDI Wallet?

No. DCQL fa parte della specifica principale di OpenID4VP e qualsiasi implementazione OpenID4VP può utilizzarlo. L'ecosistema EUDI Wallet ne è un utilizzatore di primo piano: l'Architecture and Reference Framework indica OpenID4VP con DCQL come meccanismo di presentazione che le relying party devono supportare, ed è per questo che conta in particolare per wallet e verificatori pensati per il mercato europeo.

DCQL esegue da solo la divulgazione selettiva?

No. DCQL descrive soltanto ciò che viene richiesto. La possibilità per il wallet di rivelare esattamente quegli attributi e nient'altro dipende dal formato della credenziale: sia SD-JWT VC sia ISO mdoc consentono di divulgare un sottoinsieme dei propri attributi, e l'array claims di DCQL si appoggia a questo supporto. Con un formato privo di divulgazione selettiva DCQL funzionerebbe comunque, ma il titolare dovrebbe rilasciare l'intera credenziale anche per una query su un solo attributo.

Fonti

  1. OpenID for Verifiable Presentations 1.0, sezione Digital Credentials Query Language (DCQL)
  2. EUDI Wallet Architecture and Reference Framework
  3. Specifica DIF Presentation Exchange 2.0.0

Questa pagina ha scopo informativo e non costituisce consulenza legale. Per indicazioni autorevoli rivolgersi direttamente alla OpenID Foundation e alla Commissione europea.

Parlaci della tua integrazione con l'EUDI Wallet