Present mDL and mDoc Verifiable Credentials via OID4VP

To follow this guide, you need a wallet (wallet-service) configured with an additional service like the credential store for storing received credentials. For more information on different setups, please go here.


This guide works for both the Verifier Service and the Verifier2 Service.
You will notice examples for Presentation Definitions, which are used in the draft OpenID4VP specifications implemented by the Verifier Service.
The Verifier2 Service uses the new OpenID4VP 1.0 specification, which does not support Presentation Definitions. Instead, it supports DCQL (Digital Credential Query Language).


There are several methods by which a user (wallet) can present a credential to a verifier, and all are supported by the wallet API:

  1. User may receive a direct link, which opens the wallet and prompts credential sharing.
  2. A website may display a QR code for the user to scan and share the credential.
  3. The user may manually input a credential presentation request URL string into a text field.

Credential Authorization Request URL

The authorization URL is a standardised method, as per the OID4VP specification, to communicate the needed credentials and claims from verifier to the wallet.

Example Presentation Request

openid4vp://authorize
?response_type=vp_token
&client_id=<client_id>
&response_mode=direct_post
&state=<state>
&presentation_definition=<presentation_definition>
&client_id_scheme=redirect_uri
&response_uri=<response_uri>
Presentation Definition
DCQL

The Presentation Definition for mDL and mDocs

The presentation definition specifies the criteria for the wallet to know what credentials and claims should be requested from the user and shared with the verifier.

Example for mDL

{
  "input_descriptors": [
    {
      "id": "org.iso.18013.5.1.mDL",
      "format": {
        "mso_mdoc": {
          "alg": [
            "ES256"
          ]
        }
      },
      "constraints": {
        "fields": [
          {
            "path": [
              "$['org.iso.18013.5.1']['age_over_18']"
            ],
            "intent_to_retain": false
          },
          {
            "path": [
              "$['org.iso.18013.5.1']['issue_date']"
            ],
            "intent_to_retain": false
          },
          {
            "path": [
              "$['org.iso.18013.5.1']['expiry_date']"
            ],
            "intent_to_retain": false
          }
        ],
        "limit_disclosure": "required"
      }
    }
  ]
}

The definition specifies that one credential is requested which is of the mdl format (Mdocs uses namespaces, which formally represent the document type which in this case is org.iso.18013.5.1.mDL) and requests specifically whether the holder is over 18 years old and the mDL is valid.

Steps To Fulfill Presentation Request

To fulfill the presentation request received by the verifier, we will need to perform the following steps:

  1. Find credentials matching the presentation definition in the linked credential store of the wallet.
  2. Present matched credentials

1. Find Credentials To Present

To locate the credentials that align with the dcql query provided by the verifier, we will utilize the credential store API.

CURL

Endpoint: /v1/{target}/credential-store-service-api/credentials/query/document/schema | API Reference

Example Request

curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/credential-store-service-api/credentials/query/document/schema' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '[
  {
        "id": "my_photoid",
        "format": "mso_mdoc",
        "meta": {
          "doctype_value": "org.iso.23220.photoid.1"
        },
        "claims": [
          { "path": [ "org.iso.18013.5.1", "family_name_unicode" ] },
          { "path": [ "org.iso.18013.5.1", "given_name_unicode" ] },
          { "path": [ "org.iso.18013.5.1", "issuing_authority_unicode" ] },
          {
            "path": [ "org.iso.18013.5.1", "resident_postal_code" ],
            "values": [ 1180, 1190, 1200, 1210 ]
          },
          {
            "path": [ "org.iso.18013.5.1", "issuing_country" ],
            "values": [ "AT" ]
          }
        ]
    }
]'

Response Codes

  • 200 - Matching credentials

2. Present Matched Credentials

CURL

Endpoint: /v1/{target}/wallet-service-api/credentials/present | API Reference

Example Request

curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/wallet-service-api/credentials/present' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "requestUrl": "openid4vp://authorize?client_id=did%3Ajwk%3AeyJrdHkiOiJPS1AiLCJjcnYiOiJFZDI1NTE5Iiwia2lkIjoiU05JZ1ItTHZzSEUtNkhUUGxYYUpQVDVubHRZMFpqZlA0VkpTWEwzQ2ZkMCIsIngiOiJIVWM1ZHY1eFREV3VMVmZQcFdvVXBWTjZ1QTNJNzBsVzVnNEhoMG5VaDQ0In0&request_uri=http%3A%2F%2Forg.enterprise.localhost%3A3000%2Fv1%2Forg.tenant.verifier%2Fverifier2-service-api%2Fbb3f89d1-8bc9-4d04-9418-12bc70bd76e9%2Frequest",
  "keyReference": "example.kms.key1",
  "didReference": "example.didstore.did1",
  "credentials": [
    {
      "credential": "waltid.tenant22.credential-store-wallet1.3d629d4b-4111-461d-9233-b2224fd64486",
    }
  ]
}'

Body Parameters

  • requestUrl String - An OID4VCP Authorization URL.
  • credentials (optional) Array - You can optionally provide a list of credential IDs from the linked credential store that you want to present. If you do not provide a list, the wallet will attempt to find matching credentials based on the dcql query specified in the request URL.
    For Mdocs credentials, the selective disclosure mechanism is built into the credential format itself. The wallet will automatically handle the selective disclosure of claims based on the dcql query requirements.
    If you prefer, you can also explicitly specify which fields to disclose next to the credential ID under the "disclosures" field in the credential object.
  • keyReference (optional) String - The resource ID (target) of the key which owns the credential.
  • didReference (optional) String - The DID reference of a DID stored in a linked DID Store.

Response Codes

  • 200 - Presentation was accepted

When the present endpoint is executed for mDL and mDoc credentials, the Wallet will create a Verifiable Presentation that contains the selectively disclosed claims from the mDL or mDoc credential. The selective disclosure mechanism ensures that only the claims specified in the presentation definition (or explicitly provided in the disclosures array) are shared with the verifier, while maintaining the cryptographic integrity of the credential.

Last updated on November 4, 2025