Skip to content

Claim Queries and Selective Disclosure

Claim Queries enable selective disclosure in DCQL by specifying which individual data fields within a credential the verifier needs. Rather than requesting entire credentials, verifiers can request specific claims (attributes), and wallets can respond with only those fields. This is fundamental to privacy preservation, allowing holders to share the minimum information necessary for verification.

A claim query specifies a single data field (claim) within a credential. Claims are the individual pieces of information that make up a credential—name, birth date, address, degree type, account number, etc. Claim queries identify which of these fields the verifier needs and optionally what values are acceptable.

For example, a credential might contain name, birth_date, address, and nationality. A claim query could request only the name and nationality fields, leaving birth_date and address undisclosed. This gives holders control over what information they share while ensuring verifiers receive what they need.

Traditional credential sharing often involves all-or-nothing disclosure. If a verifier needs to see one field, they receive the entire credential. This creates unnecessary privacy risks and violates data minimization principles.

Selective disclosure solves this problem. Common scenarios include:

  • Age verification: Share age_over_18 boolean rather than exact birth date
  • Address verification: Share city and postal code without street address
  • Education verification: Share degree type and institution without grades
  • Income verification: Share income bracket rather than exact salary

Claim queries make selective disclosure explicit and standardized, ensuring wallets and verifiers have a common understanding of what’s being requested and what’s being shared.

A claim query is a JSON object within the claims array of a credential query. It contains three fields:

id: A required string identifier for the claim (when using claim_sets). This ID references the claim in claim set definitions. Should be descriptive like “full_name” or “birth_date”.

path: A required array representing the path to the claim within the credential’s data structure. Each element is a string representing a key or field name. For nested structures, the path traverses the hierarchy.

values: An optional array of acceptable values for the claim. When present, the wallet should only return the claim if its actual value exactly matches one of the listed values. Used for filtering credentials based on specific attribute values.

The path array navigates to a specific field within the credential. For a flat credential structure:

"path": ["family_name"]

This selects the family_name field at the top level.

For nested structures:

"path": ["address", "postal_code"]

This selects the postal_code field within an address object.

Path expressions are straightforward compared to JSONPath or XPath. They simply list the keys to traverse from the root to the target claim.

The values field enables claim-level filtering. When specified, the wallet evaluates whether the claim’s actual value matches any listed value before including the credential:

{
"id": "postal_code",
"path": ["postal_code"],
"values": ["90210", "10001", "60601"]
}

This claim query only matches credentials where the postal_code is one of the three listed values. This is useful for eligibility checks (service availability in specific areas) or categorical matching (membership in specific organizations).

The claim_sets field within a credential query defines acceptable combinations of claims. While the claims array lists all possible claims, claim_sets expresses which combinations the verifier prefers.

Each element in the claim_sets array is itself an array of claim IDs. These inner arrays represent alternative claim combinations, ordered by preference. The wallet evaluates these options and returns the first combination it can satisfy.

The logic for evaluating claims and claim_sets:

  1. If claims is absent, no selective disclosure is requested—the entire credential is expected
  2. If claims is present but claim_sets is absent, all claims listed in claims are required
  3. If both claims and claim_sets are present, the wallet returns one claim combination from claim_sets, preferring earlier options

This layered approach enables expressing both mandatory claim requirements and privacy-preserving alternatives.

Claim sets enable privacy-preserving patterns by expressing preferences for less sensitive claims:

{
"claims": [
{ "id": "age_over_21", "path": ["age_over_21"] },
{ "id": "birth_date", "path": ["birth_date"] }
],
"claim_sets": [["age_over_21"], ["birth_date"]]
}

This requests age verification. The first option is age_over_21, a simple boolean. If the credential doesn’t support this derived claim, the second option accepts birth_date. The wallet provides the least sensitive option available, automatically preserving privacy.

A claim query for age verification using selective disclosure:

{
"id": "identity_credential",
"format": "dc+sd-jwt",
"meta": {
"vct_values": ["https://example.gov/identity"]
},
"claims": [
{ "id": "over_18", "path": ["age_over_18"] },
{ "id": "dob", "path": ["date_of_birth"] }
],
"claim_sets": [["over_18"], ["dob"]]
}

The verifier prefers age_over_18. If unavailable, date_of_birth is acceptable. The holder shares minimal information—just the boolean if their credential supports it, or the full date only if necessary.

A claim query requesting specific address components:

{
"id": "address_credential",
"format": "dc+sd-jwt",
"meta": {
"vct_values": ["https://example.com/address"]
},
"claims": [
{ "id": "city", "path": ["locality"] },
{ "id": "postal", "path": ["postal_code"] },
{ "id": "country", "path": ["country"] }
],
"claim_sets": [["city", "postal", "country"]]
}

This requests three specific address fields without requiring street address. The holder’s exact street location remains private while the verifier confirms the general location.

Claim queries work alongside credential sets. A credential set might require one of several credential types, and each credential type can have its own claim queries:

{
"credentials": [
{
"id": "passport",
"format": "mso_mdoc",
"claims": [
{ "id": "name", "path": ["full_name"] },
{ "id": "nationality", "path": ["nationality"] }
]
},
{
"id": "national_id",
"format": "mso_mdoc",
"claims": [
{ "id": "name", "path": ["given_name", "family_name"] },
{ "id": "country", "path": ["issuing_country"] }
]
}
],
"credential_sets": [
{
"options": [["passport"], ["national_id"]]
}
]
}

The holder provides either passport or national_id, and only the specified claims from whichever they choose.

In Vidos, claim queries enable fine-grained authorization policies. The Authorizer generates claim queries when policies require specific attributes rather than entire credentials. The Validator checks that presentations contain the required claims with acceptable values.

This enables privacy-preserving verification where Vidos applications request only the data they genuinely need for authorization decisions.

Claim queries enable selective disclosure in DCQL, allowing verifiers to request specific fields within credentials rather than entire documents. Through path expressions, value filtering, and claim_sets for expressing alternatives, claim queries provide the mechanism for privacy-preserving, data-minimizing credential verification.