DCQL förklarat: så begär en verifierare exakt det den behöver från en plånbok
Digital Credentials Query Language, DCQL, är det JSON-frågeformat som OpenID4VP använder i en presentationsbegäran. Det låter en förlitande part beskriva vilka intyg, och vilka uppgifter i dem, den vill se, på ett sätt som varje kompatibel plånbok kan tolka utan en skräddarsydd integration.
Problemet som DCQL löser
En företagsplånbok kan innehålla intyg i flera format: en företagsregistrering som SD-JWT VC, en yrkeskvalifikation kodad som mdoc och ett W3C verifiable credential från ett tidigare pilotprojekt. En verifierare som bara behöver bekräfta ett registreringsnummer och ett juridiskt namn har inget portabelt sätt att begära just det över olika format, utan att antingen godta hela intyget eller handkoda en separat begäran per format och per plånboksleverantör.
DCQL täpper till den luckan på begäranssidan. Det är ett enda JSON-objekt, inbäddat i OpenID4VP-auktoriseringsbegäran, som namnger en eller flera intygsfrågor, var och en knuten till ett format och en uppsättning uppgiftssökvägar. Plånboken utvärderar frågan mot sina lagrade intyg, tar reda på vilka som matchar och ber först därefter innehavaren att godkänna utlämnandet av just de uppgifterna. Verifieraren får en förutsägbar struktur att tolka, oavsett vilken plånbok innehavaren använde.
1. Verifierare
Skickar en OpenID4VP-begäran med en dcql_query
2. Plånbok
Matchar frågan mot lagrade intyg
3. Innehavare
Godkänner att bara de begärda uppgifterna lämnas ut
4. Verifierare
Tar emot en presentation per id i intygsfrågan
Så är en DCQL-fråga uppbyggd
En DCQL-fråga är ett JSON-objekt med en credentials-array och, valfritt, en credential_sets-array. Varje post i credentials är en intygsfråga. Fält markerade med M är obligatoriska i den frågan.
dcql_query
credentials[ ]
En intygsfråga per intyg du behöver
id + format
Vilket intyg, i vilket format
meta
Typfilter, till exempel vct_values
claims[ ]
Sökvägar till uppgifter som ska lämnas ut
claim_sets[ ]
Godtagbara kombinationer av uppgifter
credential_sets[ ]
Valfritt: vilka kombinationer av intygsfrågor som uppfyller begäran
| Fält | Typ | Obligatoriskt |
|---|---|---|
| id | string | M |
| format | enum: dc+sd-jwt | mso_mdoc | jwt_vc_json | ldp_vc | M |
| meta | objekt, formen beror på format | |
| claims | array av uppgiftsfrågor | |
| claim_sets | array av arrayer med uppgifts-id:n | |
| trusted_authorities | array av objekt med en typ och värden |
Varje post i claims är i sin tur ett objekt: ett id som används för att referera till den från claim_sets, en path, en array som anger var uppgiften finns i intyget (till exempel ["legal_name"] för en SD-JWT-uppgift på toppnivå eller ["org", "registration_number"] för en nästlad uppgift), och valfritt values, en lista med värden som uppgiften måste matcha.
Exempel: kontroll av företagsregistrering
Företagsregistrering
dc+sd-jwtVerifieraren säger: det här vill jag få
- ✓ Registreringsnummerreg_nopath: ["registration_number"]
- ✓ Juridiskt namnlegal_namepath: ["legal_name"]
- ✓ Registreringslandreg_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"] }
]
}
]
}Exempel på svar från plånboken
Plånboken svarar med ett vp_token-objekt där nycklarna är intygsfrågornas id:n. Varje värde är en array av presentationer. För dc+sd-jwt består en presentation av den utfärdarsignerade JWT:n, en disclosure per utlämnad uppgift och en key binding JWT som knyter den till denna begärans nonce och klient.
Vad plånboken skickar
{
"vp_token": {
"company_registration": [
"<issuer-signed JWT>~<disclosure: registration_number>~<disclosure: legal_name>~<disclosure: registration_country>~<key binding JWT>"
]
}
}Uppgifter som verifieraren ser efter validering
{
"vct": "urn:eudi:business:company-registration:1",
"registration_number": "12345678",
"legal_name": "Example Logistics B.V.",
"registration_country": "NL"
}Begära ett reservalternativ: claim_sets
claim_sets listar grupper av uppgifts-id:n i prioritetsordning. Plånboken returnerar den första grupp den helt kan uppfylla med det innehavaren faktiskt har, så att verifieraren slipper skicka två separata förfrågningar för ett exakt fall och ett reservfall.
Exempel: registreringsnummer, eller bara juridiskt namn som reserv
1. Föredraget
Returneras när intyget innehåller båda uppgifterna
2. Reserv
Returneras bara när den första uppsättningen inte kan uppfyllas
{
"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"]
]
}
]
}Här föredrar verifieraren registreringsnummer plus juridiskt namn, men godtar enbart det juridiska namnet om innehavarens intyg inte innehåller någon uppgift om registreringsnummer.
Exempel på svar: reservalternativet användes
Vad plånboken skickar
{
"vp_token": {
"company_registration": [
"<issuer-signed JWT>~<disclosure: legal_name>~<key binding JWT>"
]
}
}Uppgifter som verifieraren ser efter validering
{
"vct": "urn:eudi:business:company-registration:1",
"legal_name": "Example Logistics B.V."
}Innehavarens intyg har inget registreringsnummer, så plånboken uppfyllde den andra uppgiftsuppsättningen och lämnade ut en enda disclosure. Svaret anger inte vilken uppsättning som användes: verifieraren utläser det av de uppgifter den tar emot.
Kombinera intyg: credential_sets
credential_sets verkar en nivå ovanför claim_sets. Varje post listar options, där varje alternativ är en grupp id:n för intygsfrågor. Plånboken måste uppfylla ett alternativ i varje obligatorisk post, vilket ger verifieraren OCH- och ELLER-logik mellan intyg i en enda begäran.
Obligatorisk
Företagsregistrering
En av
Momsregistrering
En av
Intyg om bankkonto
"credential_sets": [
{ "options": [["company_registration"]] },
{ "options": [["vat_registration"], ["bank_account"]] }
]Exempel på svar: registrering plus bankkonto
Vad plånboken skickar
{
"vp_token": {
"company_registration": [
"<issuer-signed JWT>~<disclosures>~<key binding JWT>"
],
"bank_account": [
"<issuer-signed JWT>~<disclosures>~<key binding JWT>"
]
}
}Uppgifter som verifieraren ser efter validering
{
"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."
}
}Innehavaren har inget intyg om momsregistrering, så plånboken valde det andra alternativet i den andra uppsättningen. Fråge-id:n som inte användes, här vat_registration, saknas helt enkelt i vp_token.
Bara betrodda utfärdare: trusted_authorities
trusted_authorities begränsar en intygsfråga till intyg vars utfärdare backas av en myndighet som verifieraren litar på. Varje post har en typ och en lista med värden: aki för en authority key identifier, etsi_tl för en ETSI-betrodd lista eller openid_federation för ett förtroendeankare i en federation. Plånboken erbjuder bara intyg som matchar.
Exempel: en registrering från en listad utfärdare
Verifieraren säger: bara från utfärdare på den här betrodda listan
https://ec.europa.eu/tools/lotl/eu-lotl.xml
Registreringsintyg från en listad utfärdare
utfärdaren finns på den betrodda listan
✓ Matchar frågan
Registreringsintyg från en olistad utfärdare
utfärdaren finns inte på den betrodda listan
✗ Matchar inte, erbjuds inte innehavaren
{
"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"] }
]
}
]
}Exempel på svar: bara intyget från den listade utfärdaren
Vad plånboken skickar
{
"vp_token": {
"company_registration": [
"<issuer-signed JWT>~<disclosure: registration_number>~<disclosure: legal_name>~<key binding JWT>"
]
}
}Uppgifter som verifieraren ser efter validering
{
"vct": "urn:eudi:business:company-registration:1",
"registration_number": "12345678",
"legal_name": "Example Logistics B.V."
}Innehavaren hade också ett registreringsintyg från en olistad utfärdare, men plånboken erbjöd det inte. trusted_authorities är ett filter för plånboken, inte en garanti: verifieraren kontrollerar ändå själv utfärdaren mot den betrodda listan när den validerar presentationen.
Matcha ett värde: claims.values
En uppgiftsfråga kan innehålla values, en lista med strängar, heltal eller booleska värden. Plånboken returnerar bara uppgiften när dess typ och värde exakt matchar något av dem, så att en verifierare kan kontrollera ett villkor utan att först begära något annat.
Exempel: bara företag registrerade i Nederländerna eller Belgien
Verifieraren säger: bara ett företag registrerat i något av dessa länder
Nederländskt företag
registration_country: "NL"
✓ Matchar frågan
Tyskt företag
registration_country: "DE"
✗ Matchar inte, erbjuds inte innehavaren
{
"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"]
}
]
}
]
}Exempel på svar: ett nederländskt företag
Vad plånboken skickar
{
"vp_token": {
"company_registration": [
"<issuer-signed JWT>~<disclosure: legal_name>~<disclosure: registration_country>~<key binding JWT>"
]
}
}Uppgifter som verifieraren ser efter validering
{
"vct": "urn:eudi:business:company-registration:1",
"legal_name": "Example Logistics B.V.",
"registration_country": "NL"
}Ett tyskt företags intyg har registration_country "DE", så det uppfyller inte frågan och plånboken har inget att returnera för det. Verifieraren bör ändå kontrollera värdet i de validerade uppgifterna i stället för att förlita sig på plånbokens filtrering.
Formatspecifika villkor i meta
SD-JWT VC: vct_values
För dc+sd-jwt listar meta.vct_values de identifierare för intygstyper som verifieraren godtar. En fråga matchar bara ett lagrat intyg vars vct är ett av de listade värdena, så en verifierare som bara litar på en viss utfärdares typ av registreringsintyg listar exakt den identifieraren.
mso_mdoc: doctype_value och namnrymd
För mso_mdoc fastställer meta.doctype_value DocType enligt ISO 18013-5, och varje uppgiftssökväg börjar med den mdoc-namnrymd som uppgiften tillhör i stället för ett vanligt fältnamn, eftersom mdoc grupperar uppgifter per namnrymd i stället för i ett platt objekt.
Var DCQL står i dag
- DCQL definieras i själva OpenID4VP-specifikationen, inte i ett separat dokument, och har ingått i utkastet sedan mekanismen infördes för att ersätta ett tidigare beroende av DIF Presentation Exchange för OpenID4VP-förfrågningar.
- EUDI Wallet Architecture and Reference Framework anger OpenID4VP som presentationsprotokoll och därmed DCQL som den frågemekanism som förlitande parter och plånböcker i ekosystemet förväntas stödja.
- Referensimplementationer av plånböcker och verifierare i programmet EUDI Wallet Reference Implementation har samlats kring DCQL. Nya integrationer av företagsplånböcker som byggs mot OpenID4VP i dag bör därför utgå från DCQL, inte Presentation Exchange, som frågeformat för presentationsbegäranden.
Relaterade begrepp
Vanliga frågor
Hur skiljer sig DCQL från DIF Presentation Exchange?
Båda beskriver vad en verifierare vill ha från en plånbok, men DCQL är avgränsat till OpenID4VP och definieras direkt i den specifikationen, medan Presentation Exchange är en separat DIF-specifikation som även täcker andra protokoll. DCQL är medvetet mindre: det saknar input descriptor-grupper och submission requirements, och det uttrycker formatspecifika villkor, som en mdoc-doctype eller en SD-JWT VC-typ, direkt i ett frågeobjekt i stället för via ett generiskt JSON Schema-filter. EUDI Wallet-ekosystemet har standardiserat på DCQL för OpenID4VP-presentationer.
Kan en DCQL-fråga begära mer än ett intyg?
Ja. Arrayen credentials kan lista flera intygsfrågor, var och en med eget id. En plånbok som har träffar för varje post returnerar en presentation per post. Det valfria objektet credential_sets kan dessutom kräva särskilda kombinationer, till exempel godta antingen ett företagsregistreringsintyg ensamt eller ett företagsregistreringsintyg tillsammans med en UBO-förklaring, utan att fråga innehavaren två gånger.
Vilket problem löser claim_sets inom en enskild intygsfråga?
Ett intyg innehåller inte alltid alla uppgifter som en verifierare skulle vilja ha. claim_sets listar alternativa grupper av uppgifts-id:n som var för sig skulle uppfylla begäran, ordnade från mest till minst föredragen. Plånboken väljer den första grupp den helt kan uppfylla med de uppgifter innehavaren faktiskt har. På så sätt kan en verifierare begära ett exakt ID-nummer där det finns och falla tillbaka på en grövre kontroll, som en över 18-flagga, utan att skicka två separata förfrågningar.
Är DCQL specifikt för EUDI Wallet?
Nej. DCQL är en del av OpenID4VP:s kärnspecifikation och kan användas av alla OpenID4VP-implementationer. EUDI Wallet-ekosystemet är en framträdande användare: Architecture and Reference Framework anger OpenID4VP med DCQL som den presentationsmekanism som förlitande parter måste stödja. Därför är det särskilt viktigt för plånböcker och verifierare som byggs för den europeiska marknaden.
Utför DCQL själv selektivt utlämnande?
Nej. DCQL beskriver bara vad som efterfrågas. Om plånboken kan avslöja exakt de uppgifterna och inget annat beror på intygsformatet: både SD-JWT VC och ISO mdoc stöder utlämnande av en delmängd av sina uppgifter, så en DCQL claims-array bygger på det stödet. DCQL mot ett format utan selektivt utlämnande skulle fortfarande fungera, men innehavaren skulle då behöva lämna ut hela intyget även för en fråga om en enda uppgift.
Källor
Den här sidan är endast informativ och utgör inte juridisk rådgivning. För auktoritativ vägledning, kontakta OpenID Foundation och Europeiska kommissionen direkt.