DCQL (Digital Credentials Query Language)
DCQL (Digital Credentials Query Language) is a standardized query format for requesting specific credentials and claims from wallets in OpenID4VP flows. EUDIPLO uses DCQL in the dcql_query field of presentation configurations.
Overviewโ
DCQL allows verifiers to:
- Request specific credential formats (SD-JWT, mDoc, etc.)
- Select specific claims from credentials
- Define trust requirements for credential issuers
- Allow or restrict multiple matching credentials
Schema Referenceโ
The full DCQL JSON schema is available at DCQL.schema.json in the repository.
Basic Structureโ
{
"dcql_query": {
"credentials": [
{
"id": "credential-query-id",
"format": "mso_mdoc",
"meta": {
"doctype_value": "eu.europa.ec.eudi.pid.1"
},
"claims": [
{
"path": ["eu.europa.ec.eudi.pid.1", "given_name"]
},
{
"path": ["eu.europa.ec.eudi.pid.1", "family_name"]
}
],
"trusted_authorities": [
{
"type": "etsi_tl",
"values": [
{
"trustListId": "local-pid-trust-list"
}
]
}
]
}
]
}
}
Credential Query Fieldsโ
Each entry in the credentials array defines one credential query:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier for this credential query |
format | string | Yes | Credential format (e.g., mso_mdoc, dc+sd-jwt) |
meta | object | No | Format-specific metadata (e.g., doctype_value for mDoc) |
claims | array | No | Specific claims to request (see below) |
multiple | boolean | No | Allow multiple matching credentials. Default: false |
trusted_authorities | array | No | Trust requirements for credential issuers (see below) |
claim_sets | array | No | Alternative claim combinations (any matching set satisfies) |
Requesting Claimsโ
Claims are specified using JSON path arrays:
SD-JWT Formatโ
{
"id": "employee-badge",
"format": "dc+sd-jwt",
"meta": {
"vct_values": ["EmployeeBadge"]
},
"claims": [
{
"path": ["employee_id"]
},
{
"path": ["department"]
}
]
}
mDoc Formatโ
{
"id": "pid-mso-mdoc",
"format": "mso_mdoc",
"meta": {
"doctype_value": "eu.europa.ec.eudi.pid.1"
},
"claims": [
{
"path": ["eu.europa.ec.eudi.pid.1", "given_name"]
},
{
"path": ["eu.europa.ec.eudi.pid.1", "family_name"]
},
{
"path": ["eu.europa.ec.eudi.pid.1", "birthdate"]
}
]
}
Trust Authoritiesโ
To validate that a credential was issued by a trusted entity, configure trust lists per credential using the trusted_authorities field. This follows the OID4VP Trusted Authorities Query specification.
Structureโ
Each entry in trusted_authorities specifies:
type: The trust framework type. Supported values:etsi_tlโ ETSI TS 119 602 List of Trusted Entities (LoTE)openid_federationโ OpenID Federation trust anchors
values: Array of trust anchors.
ETSI Trust Listsโ
For etsi_tl, each values entry can be:
Managed local trust list pointer:
{
"type": "etsi_tl",
"values": [
{
"trustListId": "local-pid-trust-list"
}
]
}
External trust list reference:
{
"type": "etsi_tl",
"values": [
{
"url": "https://example.com/trust-list/pid-provider.jwt",
"verifierX509Der": "MIIB..."
}
]
}
When trustListId is used, EUDIPLO resolves:
- LoTE URL as
<TENANT_URL>/trust-list/{trustListId} - verifier certificate from the trust list key chain
Using Your Own Trust Listsโ
You can reference trust lists published by your own EUDIPLO instance at /{tenantId}/trust-list/{trustListId}. You can also use the <TENANT_URL> placeholder in trust list URLs, which will be replaced with the tenant's base URL at runtime.
Automatic Transformation to AKIโ
:::info Automatic transformation to aki in authorization requests
The etsi_tl format with TrustListRef objects is an internal configuration format only. When EUDIPLO builds the OID4VP authorization request sent to wallets, it automatically transforms each etsi_tl entry into the DCQL-compliant aki (Authority Key Identifier) format required by OID4VP 1.0 Final ยง6.
The transformation extracts the Subject Key Identifier (SKI, OID 2.5.29.14) from the trust anchor certificate and encodes it as a base64url string. A wallet can match credentials locally by checking whether any certificate in a credential's chain was signed by a CA whose key identifier equals one of the aki values โ without fetching external trust-list resources.
Configuration format (stored in EUDIPLO):
{ "type": "etsi_tl", "values": [{ "trustListId": "my-list" }] }
Wire format (sent to wallets):
{ "type": "aki", "values": ["<base64url-encoded-SKI>"] }
:::
Verification Behaviorโ
During verification, EUDIPLO will:
- Fetch the LoTE JWT(s) from the provided URLs
- Parse the trusted entities and their certificates
- Validate that the credential's issuer certificate chains to one of the trusted entities
- If status checks are enabled (
statusCheckModeisstrictorbest_effort), ensure the status list (if present) is signed by the revocation certificate from the same trusted entity
:::warning Trust validation is opt-in per credential
If trusted_authorities is not specified on a credential query, trust list validation is skipped for that credential. To enforce trust validation, always include trusted_authorities in your DCQL credential queries.
:::
Claim Setsโ
Claim sets define alternative combinations of claims. The credential satisfies the query if it contains all claims from any one set:
{
"id": "age-verification",
"format": "mso_mdoc",
"meta": {
"doctype_value": "eu.europa.ec.eudi.pid.1"
},
"claim_sets": [
["age_over_18"],
["birthdate"]
]
}
In this example, the credential satisfies the query if it contains either:
- The
age_over_18claim, OR - The
birthdateclaim
Multiple Credentialsโ
By default, EUDIPLO expects exactly one credential matching each query. Set multiple: true to allow multiple matching credentials:
{
"id": "employee-badges",
"format": "dc+sd-jwt",
"multiple": true,
"claims": [
{
"path": ["badge_type"]
}
]
}
Full Exampleโ
{
"dcql_query": {
"credentials": [
{
"id": "pid-mso-mdoc",
"format": "mso_mdoc",
"meta": {
"doctype_value": "eu.europa.ec.eudi.pid.1"
},
"claims": [
{
"path": ["eu.europa.ec.eudi.pid.1", "given_name"]
},
{
"path": ["eu.europa.ec.eudi.pid.1", "family_name"]
},
{
"path": ["eu.europa.ec.eudi.pid.1", "age_over_18"]
}
],
"trusted_authorities": [
{
"type": "etsi_tl",
"values": [
{
"trustListId": "eudi-pid-trust-list"
}
]
}
]
},
{
"id": "employee-badge",
"format": "dc+sd-jwt",
"meta": {
"vct_values": ["EmployeeBadge"]
},
"claims": [
{
"path": ["employee_id"]
}
]
}
]
}
}
This query requests:
- A PID (mDoc format) with name and age verification
- An employee badge (SD-JWT format) with employee ID
Both credentials must be present to satisfy the request.
Best Practicesโ
- Request only necessary claims โ Minimize data collection to protect user privacy
- Use trust lists โ Always configure
trusted_authoritiesfor production deployments - Use descriptive IDs โ Choose credential query IDs that indicate their purpose
- Test with real wallets โ Verify that your DCQL queries work with target wallet implementations
- Document claim requirements โ Keep a mapping of business requirements to DCQL claims
Related Documentationโ
- Presentation Configuration โ Configuring presentation requests
- Trust Lists โ Trust list management
- OpenID4VP Specification โ DCQL specification