Verify Mobile Driver's Licenses (ISO/IEC 18013-7 mDL) via OID4VP

This guide provides a comprehensive walkthrough for verifying an mDL based on the ISO/IEC 18103-7 standard using the walt.id Enterprise Verifier API. The verification process will utilize the OID4VP protocol.

Enterprise Service Dependencies

To verify credentials, you need to have the following enterprise services setup:

  1. Verifier Service - Have a running verifier service. Setup instructions can be found here.

Verification Process

  1. Set mDL as the credential type to request from a user.
  2. Specify the claims from the mDL that are subject to presentation.
  3. Optionally provide a success and failure redirect URL, which the user will be redirected to after the verification process is completed.

After you have provided the required information, the Verifier API:

  1. Generates an appropriate Presentation Definition.
  2. Returns a URL which can passed to a compliant wallet to fulfill the request.

If you have provided a success or failure redirect URL, the user will be redirected to that URL. You can then access the verification results by using the id of the verification session, which can be found in the URL generated by the API, as well as in the query or path parameters of the redirect URL.

Example Verification Request

CURL

Endpoint: /v1/{target}/verifier-service-api/credentials/verify | API Reference

Example Request

curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/verifier-service-api/credentials/verify' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'authorizeBaseUrl: mdoc-openid4vp://' \
  -H 'responseMode: direct_post.jwt' \
  -H 'successRedirectUri: https://example.com/success?id=$id' \
  -H 'errorRedirectUri: https://example.com/error?id=$id' \
  -H 'statusCallbackUri: https://example.com/verificationResult' \
  -H 'statusCallbackApiKey: myAPIKey' \
  -H 'stateId: myUniqueStateValue' \
  -H 'Content-Type: application/json' \
  -d '{
  "request_credentials": [
    {
      "id": "mDL-request",
      "input_descriptor": {
        "id": "org.iso.18013.5.1.mDL",
        "format": {
          "mso_mdoc": {
            "alg": [
              "ES256"
            ]
          }
        },
        "constraints": {
          "fields": [
            {
              "path": [
                "$['org.iso.18013.5.1']['birth_date']"
              ],
              "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"
        }
      }
    }
  ],
  "trusted_root_cas": [
    "-----BEGIN CERTIFICATE-----\nMIIBtDCCAVmgAwIBAgIUAOXLkeu9penFRno6oDcOBgT1odYwCgYIKoZIzj0EAwIwKDELMAkGA1UEBhMCQVQxGTAXBgNVBAMMEFdhbHRpZCBUZXN0IElBQ0EwHhcNMjUwNjAyMDYzOTQ0WhcNNDAwNTI5MDYzOTQ0WjAoMQswCQYDVQQGEwJBVDEZMBcGA1UEAwwQV2FsdGlkIFRlc3QgSUFDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAZGrRN7Oeanhn7MOaGU6HhaCt8ZMySk/nRHefLbRq8lChr+PS6JqpCJ503sEvByXzPDgPsp0urKg/y0E+F7q9+jYTBfMB0GA1UdDgQWBBTxCn2nWMrE70qXb614U14BweY2azASBgNVHRMBAf8ECDAGAQH/AgEAMBoGA1UdEgQTMBGGD2h0dHBzOi8vd2FsdC5pZDAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwIDSQAwRgIhAOM37BjC48KhsSlU6mdJwlTLrad9VzlXVKc1GmjoCNm1AiEAkFRJalpz62QCOby9l7Vkq0LAdWVKiFMd0DmSxjsdT2U=\n-----END CERTIFICATE-----\n"
  ],
  "openid_profile": "ISO_18013_7_MDOC"
}'

Path Parameters

  • orgID: Your organization ID (e.g., test for test.enterprise-sandbox.waltid.dev)
  • target: The verifier service target path (e.g., waltid.verifier1)

Header Parameters

  • Authorization: Bearer token authentication is required for enterprise stack
  • authorizeBaseUrl: Should be set to mdoc-openid4vp:// for mDL verification
  • responseMode: Must be set to direct_post.jwt for mDL verification
  • successRedirectUri (optional): Used to redirect the user if verification is successful. You can use the $id placeholder to get access to the id of verification session in your application in order to retrieve the verification results. E.g. /success?id=$id will be replaced with /success?id=1234567890
  • errorRedirectUri (optional): Used to redirect the user if verification is unsuccessful. You can use the $id placeholder to get access to the id of verification session in your application in order to retrieve the verification results. E.g. /error?id=$id will be replaced with /error?id=1234567890
  • statusCallbackUri (optional): URL that should be called when the presentation request has been fulfilled by a wallet. The request sent will be a POST including the whole presentation result.
  • statusCallbackApiKey (optional): If the endpoint you provide via statusCallbackUri is protected, you can use the statusCallbackApiKey to authenticate. The provided key will be appended as Authorization Header to the request.
  • stateId (optional): Overwrite the unique state value which gets created for each verification request with your own.

Body

{
  "request_credentials": [
    {
      "id": "mDL-request",
      "input_descriptor": {
        "id": "org.iso.18013.5.1.mDL",
        "format": {
          "mso_mdoc": {
            "alg": [
              "ES256"
            ]
          }
        },
        "constraints": {
          "fields": [
            {
              "path": [
                "$['org.iso.18013.5.1']['birth_date']"
              ],
              "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"
        }
      }
    }
  ],
  "trusted_root_cas": [
    "-----BEGIN CERTIFICATE-----\nMIIBtDCCAVmgAwIBAgIUAOXLkeu9penFRno6oDcOBgT1odYwCgYIKoZIzj0EAwIwKDELMAkGA1UEBhMCQVQxGTAXBgNVBAMMEFdhbHRpZCBUZXN0IElBQ0EwHhcNMjUwNjAyMDYzOTQ0WhcNNDAwNTI5MDYzOTQ0WjAoMQswCQYDVQQGEwJBVDEZMBcGA1UEAwwQV2FsdGlkIFRlc3QgSUFDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAZGrRN7Oeanhn7MOaGU6HhaCt8ZMySk/nRHefLbRq8lChr+PS6JqpCJ503sEvByXzPDgPsp0urKg/y0E+F7q9+jYTBfMB0GA1UdDgQWBBTxCn2nWMrE70qXb614U14BweY2azASBgNVHRMBAf8ECDAGAQH/AgEAMBoGA1UdEgQTMBGGD2h0dHBzOi8vd2FsdC5pZDAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwIDSQAwRgIhAOM37BjC48KhsSlU6mdJwlTLrad9VzlXVKc1GmjoCNm1AiEAkFRJalpz62QCOby9l7Vkq0LAdWVKiFMd0DmSxjsdT2U=\n-----END CERTIFICATE-----\n"
  ],
  "openid_profile": "ISO_18013_7_MDOC"
}

Body Parameters

  • request_credentials: An array of objects detailing the credentials to be requested from the user. For mDL credentials:
    • id: A unique identifier for the credential request
    • input_descriptor: Contains the credential specification
      • id: Must be "org.iso.18013.5.1.mDL" for mDL credentials
      • format: Must be "mso_mdoc" for mDL credentials
      • constraints: Defines which fields to request and validation rules
        • fields: Array of field specifications with paths to the requested data
        • limit_disclosure: Set to "required" for mDL verification
  • trusted_root_cas: List of trusted IACA root certificates used to verify the authenticity of the presented mDL credential. These are PEM-encoded X.509 certificates.
  • openid_profile: Must be set to "ISO_18013_7_MDOC" for mDL verification.

Example Response

The verification endpoint will return a presentation session with a URL that can be used to complete the verification process:

mdoc-openid4vp://authorize?client_id=waltid.verifier1&request_uri=https://test.enterprise-sandbox.waltid.dev/v1/waltid.verifier1/verifier-service-api/openid4vc/request&response_type=vp_token&response_mode=direct_post.jwt&scope=openid&state=1234567890

Presenting the Credential via walt.id Wallet

Using the URL returned by the verification request, we can fulfill the request using the hosted wallet by walt.id. Either show the URL as QR code and scan it with a camera or provide the URL as is in the text field below the camera once you click on "Scan to receive or present credentials" in the web wallet credentials overview page in the top right corner.

Retrieving the Verification Status

After the user presents the credential(s), you can verify the status by performing the following call with the state value obtained from the URL query params you shared with the user previously.

Example

CURL
mdoc-openid4vp://authorize...state=waltid.tenant1.verifier1.fb94470b-bcee-4ed7-93f5-906a4f5f585d...

Making the call to receive the verification result

curl -X 'GET' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/verifier-service-api/credentials/sessions/view' \
  -H 'accept: */*'
  -H 'Authorization: Bearer {yourToken}'

Path Parameters

  • orgID: - When performing operations within an organization, it is essential to use the organization's Base URL or another valid host alias. For example, if your organization is named test, your default Base URL will be test.enterprise-sandbox.walt.dev when using the sandbox environment.
  • target: resourceIdentifier - The target indicates the organization + tenant + verifier service + sessionID to request ({organizationID}.{tenantID}.{verifierServiceID}.{sessionID}), e.g. waltid.tenant1.verifier1.fb94470b-bcee-4ed7-93f5-906a4f5f585d
Last updated on August 4, 2025