Quick mdoc and mDL guide
This guide provides the minimal steps to issue an ISO 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
Generate a key pair using either
ECDSA
orEDDSA
. 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
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
Submit the CSR to a Certificate Authority (CA). The CA must support and use:
- SHA-256
mdl
profile
Upload the signed certificate
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:
-
Set the credential format as ISO mdoc
-
Set the revocation method as MSO (Mobile Security Object)
-
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 type | mdoc DocType |
---|---|
Standard mDL | org.iso.18013.5.1.mDL |
eIDAS PIDs | eu.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.
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 type | mdoc DocType |
---|---|
Standard mDL | org.iso.18013.5.1 |
eIDAS PID | eu.europa.ec.eudi.pid.1 |
US mDL - AAMVA | org.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.
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.
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>' \