How to Issue Mobile Driver's Licenses (ISO/IEC 18013-5 mDLs) via OID4VCI with walt.id Enterprise

This guide provides a comprehensive walkthrough for issuing an mDL credential based on the ISO/IEC 18103-5 standard using the walt.id Enterprise Issuer API. The issuance process will utilize the OID4VCI protocol.

Enterprise Service Dependencies

To issue a credential, you need to have the following enterprise services setup:

  1. Issuer Service - Have a running issuer service. Setup instructions can be found here.
  2. KMS Service - Have a running KMS service. Setup instructions can be found here.

Preparing for Issuance: Key Components

The mobile driver's license (mDL) ecosystem builds on established PKI principles that employ X.509 digital certificates, while introducing domain-specific roles and data models. Its main components are:

  1. IACA — Issuing Authority Certification Authority: This is an authority that serves as the root of trust vouching for authorized credential issuers and is represented by a self-signed X.509 digital certificate that is published to verifiers.
  2. DS — Document Signer (Credential Issuer): This is the entity that issues and cryptographically signs mDL credential(s). It holds a private key and an X.509 digital certificate issued by an IACA. Typically, DS certificates are short-lived and are rotated periodically.
  3. The mDL Claims: The mDL is a verifiable credential that contains claims about the subject (holder), such as name, birthdate and driving privileges. The ISO/IEC 18103-5 standard document defines a set of mandatory fields (e.g., family_name, birth_date) that must be included in every mDL, as well as a set of optional fields (e.g., age_over_NN attestations, height, weight, sex).

Example mDL Credential in JSON format:

{
  "family_name": "Doe",
  "given_name": "John",
  "birth_date": "1986-03-22",
  "issue_date": "2019-10-20",
  "expiry_date": "2024-10-20",
  "issuing_country": "AT",
  "issuing_authority": "AT DMV",
  "document_number": "123456789",
  "portrait": [ 141, 12 ],
  "driving_privileges": [
    {
      "vehicle_category_code": "A",
      "issue_date": "2018-08-09",
      "expiry_date": "2024-10-20"
    },
    {
      "vehicle_category_code": "B",
      "issue_date": "2017-02-23",
      "expiry_date": "2024-10-20"
    }
  ],
  "un_distinguishing_sign": "AT"
}

Note: mDLs are encoded in CBOR, which is a binary format and is shown in JSON representation above for readability purposes. Claims values that are encoded as JSON integer arrays, e.g., the portrait claim's value, represent byte arrays.

Issuing an mDL

In this section, we'll walk through the steps required to successfully issue an mDL using the Enterprise Stack Issuer API.

Note: At the moment, you can only use secp256r1 keys to issue mDLs.

Prerequisites

Before issuing mDLs, you need to have:

  1. IACA and Document Signer Certificates: The Enterprise Stack does not provide onboarding endpoints for IACA and Document Signer certificates. You need to obtain these certificates through external means or use the Community Stack onboarding functionality.
    For IACA and Document Signer onboarding, you can:
    • Use the Community Stack mDL onboarding guide to generate the required certificates
    • Import existing certificates into your Enterprise Stack key management system
    • Use external PKI services to generate the required certificates
  2. Issuer Service Configuration: Ensure your issuer service is properly configured with the required mDL signing keys.

Step 1: Configure mDL Credential Type

First, ensure your issuer service supports the mDL credential type. When creating an issuer service, include the mDL configuration:

{
  "type": "issuer",
  "baseUrl": "https://your-issuer.example.com",
  "kms": "your-kms-service",
  "tokenKeyId": "your-signing-key",
  "supportedCredentialTypes": {
    "org.iso.18013.5.1.mDL": {
      "format": "mso_mdoc",
      "credentialDefinition": {
        "type": ["org.iso.18013.5.1.mDL"]
      },
      "docType": "org.iso.18013.5.1.mDL"
    }
  }
}

Step 2: Issue an mDL Credential

Use the Enterprise Stack credential issuance endpoint to issue mDL credentials:

CURL

Endpoint: /v1/{target}/issuer-service-api/credentials/issue | API Reference

Example Request

curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/issuer-service-api/credentials/issue' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {yourToken}' \
  -d '{
  "issuerKeyId": "your-signing-key-id",
  "credentialConfigurationId": "org.iso.18013.5.1.mDL",
  "credentialData": {
  "issuerKeyId": "waltid.tenant2.kms1.secp-r1",
  "credentialConfigurationId": "org.iso.18013.5.1.mDL",
  "credentialData": {
    "org.iso.18013.5.1": {
      "family_name": "Doe",
      "given_name": "John",
      "birth_date": "1986-03-22",
      "issue_date": "2019-10-20",
      "expiry_date": "2024-10-20",
      "issuing_country": "AT",
      "issuing_authority": "AT DMV",
      "document_number": "123456789",
      "portrait": [
        141,
        182,
        121,
        111,
        238,
        50,
        120,
        94,
        54,
        111,
        113,
        13,
        241,
        12,
        12
      ],
      "driving_privileges": [
        {
          "vehicle_category_code": "A",
          "issue_date": "2018-08-09",
          "expiry_date": "2024-10-20"
        },
        {
          "vehicle_category_code": "B",
          "issue_date": "2017-02-23",
          "expiry_date": "2024-10-20"
        }
      ],
      "un_distinguishing_sign": "AT"
    }
  },
  "x5Chain": [
    "-----BEGIN CERTIFICATE-----\nMIICCDCCAa2gAwIBAgIUDo8kr194t6sttt6KL3YcnMtcaYYwCgYIKoZIzj0EAwIwJDELMAkGA1UEBhMCVVMxFTATBgNVBAMMDEV4YW1wbGUgSUFDQTAeFw0yNTA1MjkwNzE4MzlaFw0yNjA4MjkwNzE4MzlaMCIxCzAJBgNVBAYTAlVTMRMwEQYDVQQDDApFeGFtcGxlIERTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGWKpdL3jPoPJ5wKgSA+jxS2jgp+ZUDE6sIQbeB86vF0XfEDAf3r/FVyJXuYVCyVT95FCA/7mlJmI1/xuMygZ+qOBvjCBuzAfBgNVHSMEGDAWgBSMIxGx+iVN4rkOzoyo5aPk3HTUFDAdBgNVHQ4EFgQU7S49LSeg/e0onfT44FVbL/rSKnswDgYDVR0PAQH/BAQDAgeAMCMGA1UdEgQcMBqGGGh0dHBzOi8vaWFjYS5leGFtcGxlLmNvbTAVBgNVHSUBAf8ECzAJBgcogYxdBQECMC0GA1UdHwQmMCQwIqAgoB6GHGh0dHBzOi8vaWFjYS5leGFtcGxlLmNvbS9jcmwwCgYIKoZIzj0EAwIDSQAwRgIhAMuSq75BPBXXBWGtIMd57fhRqpKf3Yzl3ldDdoQsK2xEAiEA/dmWLMLiJPV3UzmQS5MUHtn611z0VlL/k3YAdaVJ51c=\n-----END CERTIFICATE-----\n"
  ]
}'

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 + issuer service with which to execute the credential issuance ({organizationID}.{tenantID}.{issuerServiceID}), e.g. waltid.tenant1.issuer1

Body

{
  "issuerKeyId": "your-signing-key-id",
  "credentialConfigurationId": "org.iso.18013.5.1.mDL",
  "credentialData": {
    "org.iso.18013.5.1": {
      "family_name": "Doe",
      "given_name": "John",
      "birth_date": "1986-03-22",
      "issue_date": "2019-10-20",
      "expiry_date": "2024-10-20",
      "issuing_country": "AT",
      "issuing_authority": "AT DMV",
      "document_number": "123456789",
      "portrait": [
        141,
        182,
        121,
        111,
        238,
        50,
        120,
        94,
        54,
        111,
        113,
        13,
        241,
        12,
        12
      ],
      "driving_privileges": [
        {
          "vehicle_category_code": "A",
          "issue_date": "2018-08-09",
          "expiry_date": "2024-10-20"
        },
        {
          "vehicle_category_code": "B",
          "issue_date": "2017-02-23",
          "expiry_date": "2024-10-20"
        }
      ],
      "un_distinguishing_sign": "AT"
    }
  },
  "x5Chain": [
    "-----BEGIN CERTIFICATE-----\nMIICCDCCAa2gAwIBAgIUDo8kr194t6sttt6KL3YcnMtcaYYwCgYIKoZIzj0EAwIwJDELMAkGA1UEBhMCVVMxFTATBgNVBAMMDEV4YW1wbGUgSUFDQTAeFw0yNTA1MjkwNzE4MzlaFw0yNjA4MjkwNzE4MzlaMCIxCzAJBgNVBAYTAlVTMRMwEQYDVQQDDApFeGFtcGxlIERTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGWKpdL3jPoPJ5wKgSA+jxS2jgp+ZUDE6sIQbeB86vF0XfEDAf3r/FVyJXuYVCyVT95FCA/7mlJmI1/xuMygZ+qOBvjCBuzAfBgNVHSMEGDAWgBSMIxGx+iVN4rkOzoyo5aPk3HTUFDAdBgNVHQ4EFgQU7S49LSeg/e0onfT44FVbL/rSKnswDgYDVR0PAQH/BAQDAgeAMCMGA1UdEgQcMBqGGGh0dHBzOi8vaWFjYS5leGFtcGxlLmNvbTAVBgNVHSUBAf8ECzAJBgcogYxdBQECMC0GA1UdHwQmMCQwIqAgoB6GHGh0dHBzOi8vaWFjYS5leGFtcGxlLmNvbS9jcmwwCgYIKoZIzj0EAwIDSQAwRgIhAMuSq75BPBXXBWGtIMd57fhRqpKf3Yzl3ldDdoQsK2xEAiEA/dmWLMLiJPV3UzmQS5MUHtn611z0VlL/k3YAdaVJ51c=\n-----END CERTIFICATE-----\n"
  ]
}

Body Parameters

  • issuerKeyId: String - The ID of the signing key to use for credential issuance
  • credentialConfigurationId: String - Must be "org.iso.18013.5.1.mDL" for mDL credentials
  • credentialData: JSON - The mDL credential data containing all required and optional fields
  • authenticationMethod: String - Authentication method for the issuance session (default: "PRE_AUTHORIZED")
  • expiresInSeconds: Number - Session expiration time in seconds (default: 300)
  • x5Chain: Array of Strings - Array of Strings - The X.509 certificate chain for the Document Signer, starting with the DS certificate.

Example Response

The issuance endpoint will return a credential offer URL that can be used to complete the issuance process:

openid-credential-offer://waltid.enterprise.test.waltid.cloud/?credential_offer_uri=https%3A%2F%2Fwaltid.enterprise.test.waltid.cloud%2Fv1%2Fwaltid.tenant2.issuer-mdl%2Fissuer-service-api%2Fopenid4vc%2Fdraft13%2Fcredential-offer%3Fid%3D38672f8b-bed0-4e29-b6db-c0e2580a7fa0

Step 4: Receive the Credential Offer

The created credential offer can now be embedded into a QR code for users to scan with their mobile wallet or pasted manually into the credential offer field of our web wallet.

Try It Out: Use our web wallet for a practical demonstration. After logging in, click the 'request credential' button and paste the received Offer URL into the text field below the camera.

🎉 Congratulations, you've issued a mDL using OID4VCI! 🎉

Last updated on August 4, 2025