Skip to main content

Quick mdoc and mDL guide

This guide provides the minimal steps to issue an ISO mdoc or mDL.

mdoc or mDL?

"mdoc" is a credential format and "mDL" is a mobile driving license in the mdoc format. You can define and issue both types of credentials with this system.

When you create your credential schema, you will provide a DocType parameter; this is where you specify whether you are issuing an mDL or some other kind of credential.

Prerequisites

  • Procivis One is running, either the Core or the Desk

Add a certificate identifier

  • If you already have Document Signing Certificate (DSC) in your system, skip to the issuing instructions
  • If you need to add a DSC, start here.

Generate a key pair

  1. Generate a key pair using either ECDSA or EDDSA. Remember the key's name as you will need to select it later.

Using the API?

Your call to generate a key pair will look like this:

curl -L '/api/key/v1' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <TOKEN>' \
-d '{
"keyType": "ECDSA",
"name": "My first certificate key",
"organisationId": "{{YOUR-ORG-ID}}", // Not needed for the Desk API
"storageType": "INTERNAL"
}'

Store the returned key ID for later use.

Generate a CSR

  1. Using the new key you created, generate a CSR.

  • Select the "ISO mDL" profile
  • Provide a "Common name" to be the subject of the DSC
  • Optionally provide other requested fields

The system returns your new .csr file.

Using the API?

Your call to generate a CSR will look like this:

curl -L '/api/key/v1/{{YOUR-KEY-ID}}/generate-csr' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <TOKEN>' \
-d '{
"profile": "MDL", // Provides ISO standard extensions
"subject": {
"commonName": "www.yourdomain.com"
}
}'

The API returns your new CSR.

Get the CSR signed

  1. Submit the CSR to a Certificate Authority (CA). The CA must support and use:

  • SHA-256
  • mdl profile

Upload the signed certificate

  1. Add a new certificate identifier, uploading the file in PEM format. You must select the same key you used to create the CSR.

  • If your CA included Certificate Revocation List (CRL) pointers in your certificate, the system will validate your certificate against the referenced CRLs.
Using the API?

Your call to create an identifier will look like this:

curl -L '/api/identifier/v1' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <TOKEN>' \
-d '{
"name": "My certificate identifier",
"certificates": [
{
"chain": "-----BEGIN CERTIFICATE-----\r\nMI...{{rest-of-cert}}...3Lw=\r\n-----END CERTIFICATE-----\r\n",
"keyId": "{{YOUR-KEY-ID}}"
},
"organisationId": "{{YOUR-ORG-ID}}", // Not needed for the Desk API
]
}'

Store the returned identifier ID for later use during issuance.

Issue an mdoc or mDL

As soon as you have a valid signing certificate with the mdl profile in the system you can start issuing mdocs and mDLs.

Create a credential schema

Create a credential schema as you normally would, making sure to set the following parameters:

  1. Set the credential format as ISO mdoc

  2. Set the revocation method as MSO (Mobile Security Object)

  3. Document type = Set according to what you will issue

You need to specify the DocType of the credential you will issue. Here are a few examples:

Credential typemdoc DocType
Standard mDLorg.iso.18013.5.1.mDL
eIDAS PIDseu.europa.ec.eudi.pid.1

This is generally determined by the ecosystem in which you intend to operate, and correct entry is important for interoperability, but it is also possible to define your own DocType if there is no existing standard with which you need to interoperate.

  1. Define your namespace(s)

In addition to the DocType, the mdoc standard uses a "namespace" to define the sets of claims you are issuing. Here are some namespace examples:

Credential typemdoc DocType
Standard mDLorg.iso.18013.5.1
eIDAS PIDeu.europa.ec.eudi.pid.1
US mDL - AAMVAorg.iso.18013.5.1.aamva
How namespaces work

The standard mDL namespace includes claims like:

  • family_name
  • given_name
  • height

Some implementations then add their own namespaces to define new data elements. The AAMVA implementation of mDL, for example, adds claims like:

  • domestic_driving_privileges
  • organ_donor
  • veteran

You can include more than one namespace in an mdoc credential. If you issue an mDL with both the standard mDL namespace and the AAMVA namespace, an international verifier might want to only request data from the standard mDL namespace while a U.S.-based verifier may want to also request data from the AAMVA namespace.

In Procivis One, define your namespaces using top-level object claims. To issue a standard mDL, the top object is org.iso.18013.5.1, then that object contains all the data elements you want to make claims about.

To add additional namespaces, add another top-level object and include the desired claims in that object.

Using the API?

Use schemaId to define your DocType. Your call to create a credential schema will look like this:

curl -L '/api/credential-schema/v1' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <TOKEN>' \
-d '{
"claims": [
{
"array": false,
"claims": [
{
"array": false,
"claims": [],
"datatype": "STRING",
"key": "family_name", // A data element from the namespace
"required": true
},
{
"array": false,
"claims": [],
"datatype": "STRING",
"key": "given_name",
"required": true
},
{
"array": false,
"claims": [],
"datatype": "STRING",
"key": "height",
"required": true
},
{
"array": false,
"claims": [],
"datatype": "STRING",
"key": "eye_colour",
"required": true
}
],
"datatype": "OBJECT",
"key": "org.iso.18013.5.1", // Define a namespace
"required": true
}
],
"format": "MDOC",
"name": "EXAMPLE_SCHEMA",
"revocationMethod": "MDOC_MSO_UPDATE_SUSPENSION",
"schemaId": "org.iso.18013.5.1.mDL", // Define the DocType
"walletStorageType": "SOFTWARE"
}'

Store the returned schema ID for later use during issuance.

Create and issue a credential

Credential creation and issuance of mdocs and mDLs follows the same pattern as with other formats.

  1. Create a credential from your mdoc credential schema, filling in the claim data. Be sure to:

  • use the ID of your certificate identifier as the "Issuer"
  • use OpenID4VCI
Using the API?

Your call to create a credential will look like this:

curl -L '/api/credential/v1' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <TOKEN>' \
-d '{
"claimValues": [
{
"claimId": "bcebd641-804d-41a2-bbee-7969a01b563e",
"path": "org.iso.18013.5.1/family_name",
"value": "example"
},
{
"claimId": "02d3494e-3cea-4d4f-9215-7d6ed4dce656",
"path": "org.iso.18013.5.1/given_name",
"value": "example"
},
{
"claimId": "cc1409da-467a-416d-959b-ff4ca1d1966f",
"path": "org.iso.18013.5.1/height",
"value": "example"
},
{
"claimId": "2ea56f1b-a7a2-43b4-aee4-5470128ed3e2",
"path": "org.iso.18013.5.1/eye_colour",
"value": "example"
}
],
"credentialSchemaId": "87485b79-db81-4b6a-acca-4d2bde064e68",
"protocol": "OPENID4VCI_DRAFT13",
"issuer": "e023c45f-585e-4995-9b80-ef7ba81943e3"
}'

Store the returned credential ID for later use during issuance.

  1. Issue the credential: the system generates a QR code which you can share with the wallet holder.

Using the API?

Your call to issue the credential will look like this:

curl -L '/api/credential/v1/{{CREDENTIAL-ID}}/share' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <TOKEN>' \