How to setup mDocs online verification
mDocs are digital credentials based on the ISO/IEC 18013-5 standard and DTS 18013-7 technical specification, designed to be stored on a holder’s mobile device and support both in-person or remote (online) verification workflows.
The purpose of this guide is to explain how to configure an end-to-end online verification workflow of mDocs. This can include different sets of capabilities:
- Adding online verification capabilities to a web application.
- Adding online presentation capabilities to a digital wallet application.
Prerequisites
- We recommend you make yourself familiar with the following concepts to support your
understanding of the implementation described in this page:
- What is Credential verification?
- What are mDocs?
- What are online verification workflows?
- How is the end-to-end workflow implemented?
- You will need access to a MATTR VII tenant and obtain an access token that enables you to make API requests. This is only required if you are implementing verification capabilities.
- You will need to access and install one of the MATTR Pi Wallet/Holder SDKs (only required for holding capabilities) and the Verifier Web SDK (only required for verification capabilities).
- You will need an mDoc stored in your digital wallet. For testing purposes, you can use the MATTR Labs Montcliff DMV portal to issue an mDoc into your digital wallet.
Overview
The configuration process includes the following steps:
- Configure the MATTR VII Verifier tenant.
- Add online presentation capabilities into a web application.
- Integrate a backend into the verification workflow (optional).
- Add online verification capabilities into a wallet application.
Configure the MATTR VII Verifier tenant
This step is only required if you wish to implement verification capabilities. If you are only implementing holding capabilities, you can skip to step 3.
The MATTR VII tenant is used to interact with the digital wallet as per OID4VP and ISO/IEC 18013-7 to request and verify mDocs. To enable this, you must first create a Verifier configuration on this tenant.
Create Verifier configuration
The verifier configuration is used to define the following:
- What wallet applications the verifier can interact with.
- How to invoke these wallet applications.
- How to establish trust with this verifier tenant.
- Workflow specific settings (e.g. cross-device/same-device).
- How to handle the verification results.
Request
Make a request of the following structure to your tenant to create a Verifier configuration:
PUT /v2/presentations/configuration
Request body
{
"walletProviders": [
{
"id": "my-wallet-id",
"authorizationEndpoint": "mdoc-openid4vp://"
}
],
"domains": ["example-verifier-web-application.com"],
"supportedMode": "all",
"redirectUris": ["https://example-verifier-web-application.com/presentation/callback"],
"certificateCommonName": "{tenantDomain} Verifier",
"certificateCountry": "NZ",
"display": {
"logoImage": {
"url": "https://example-logo-image-url.com",
"altText": "logo image"
},
"headerText": "Share your information.",
"bodyText": "Please scan the QR code to the right to provide information required for this interaction.",
"privacyPolicyUrl": "https://example-privacy-policy.com",
"primaryColorHex": "#FFFFFF"
},
"resultAvailableInFrontChannel": true
}
-
walletProviders
: This optional array can be used to define the digital wallets the tenant can create online presentation workflows with, and what URL schemes should be used to invoke these wallets.Incoming presentation verification requests can include a unique identifier of the wallet they want to invoke as part of the verification workflow:
- If an identifier is provided and matches the
id
of one of the objects in thewalletProviders
array, the verifier tenant will invoke that specific wallet using its configuredauthorizationEndpoint
. - If an identifier is provided and does not match the
id
of any of the objects in thewalletProviders
array, the request will fail. - If an identifier is not provided, the verifier tenant will use
mdoc-openid4vp://
(default OID4VP scheme) to invoke any wallet.
- If an identifier is provided and matches the
-
domains
: List of fully qualified domain names of verifier web applications who can request to create an online presentation session. This ensures the verifier tenant only accepts requests from known and trusted web applications. Note that localhost is not supported. You can use local tunneling services for testing. -
supportedMode
: Indicates whether a verifier supports only a same device flow, a cross device flow, or both. -
redirectUris
: Only required for same-device flows, and used to redirect the user back to the web application after completing interactions with the digital wallet. This can be any URI, including custom URI schemes. -
certificateCommonName
: Used to define the Common name of the verifier root certificate that will be created as part of this request. Wallets that are implementing certificate-based trust should be paying extra attention to this value as it would be used by the user to establish trust with the verifier. -
certificateCountry
: Used to define the ISO 31661 alpha-2 country code of the verifier root certificate that will be created as part of this request. -
display
: Only required for cross-device flows, and used to adjust the iframe modal appearance.logoImage
: Logo to be displayed on the top left corner of the iframe modal.headerText
: Header text displayed in the iframe modal.bodyText
: Optional body text displayed in the iframe modal, explaining the context in which the credentials will be shared.privacyPolicyUrl
: Optional privacy policy url to be displayed in the iframe modal.primaryColorHex
: Optional hex rgb triplet to indicate the primary color of the iframe modal.
-
resultAvailableInFrontChannel
: Indicating whether or not the verification result should be returned directly to the web application (true
) or only via a configured back-end (false
).
Response
A successful 200 response indicates that Verifier configuration has been created/updated.
The response will include a certificatePem
property, which is a PEM representation of the verifier
root certificate created to represent this tenant. We will use it to establish trust between your
wallet application and this verifier.
Configure trusted issuers
You must configure trusted issuers on your MATTR VII verifier tenant, as presented mDocs will only be verified if they had been issued by a trusted issuer.
This is achieved by providing the PEM certificate of the IACA used by these issuers to sign mDocs. This certificate can be retrieved in one of two ways:
- The Issuer can provide it directly to the Verifier out of band.
- The Verifier can retrieve it from the Issuer’s metadata:
- Make a GET request to the Issuer’s
/.well-known/openid-credential-issuer
endpoint. - Retrieve the
mdoc_iacas_uri
element from the response. - Make a GET request to that URI to retrieve the IACAs list (for example for a MATTR VII Issuer
tenant this URI would be
{tenant_url}/v1/openid/iacas
).
- Make a GET request to the Issuer’s
Request
Make a request of the following structure to your tenant to create a Truster Issuer:
POST /v2/credentials/mobile/trusted-issuers
Request body
{
"certificatePem": "-----BEGIN CERTIFICATE-----\r\nMIICUDCCAfWgAwIBAgIKVVqBlVonWFs3lTAKBggqhkjOPQQDAjAkMQswCQYDVQQG\r\nEwJOWjEVMBMGA1UEAwwMRXhhbXBsZSBJQUNBMB4XDTI0MDExMTAzMjYwMFoXDTM0\r\nMDEwODAzMjYwMFowJDELMAkGA1UEBhMCTloxFTATBgNVBAMMDEV4YW1wbGUgSUFD\r\nQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOHxm9MYkCvIvZc/MyoWGul8+tla\r\nFSSRVkDllFERbO/Tg7DOj4CJfYrhDJEuV04eRgcowBDhr9W/bvnTMZMa/RijggEN\r\nMIIBCTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E\r\nFgQUpS3hOCbmCUwu8n91X9CLS682cOkwOwYDVR0SBDQwMoYwaHR0cHM6Ly9odWRz\r\nb24tdGVuYW50LTAwMS52aWkuYXUzMDEubWF0dHJsYWJzLmlvMIGGBgNVHR8EfzB9\r\nMHugeaB3hnVodHRwczovL2h1ZHNvbi10ZW5hbnQtMDAxLnZpaS5hdTMwMS5tYXR0\r\ncmxhYnMuaW8vdjIvY3JlZGVudGlhbHMvbW9iaWxlL2lhY2FzL2VkNzQzMTllLTcy\r\nYTYtNDQwMS1iM2E1LTk0ZTk4MGZiZWJlYS9jcmwwCgYIKoZIzj0EAwIDSQAwRgIh\r\nAJxWGZvntq+hymL7zWwrlZo1Jz1+lWglu/MESdmUhTNFAiEAg+x5e3TzBxgHneIM\r\nVpTmZNOyZI3Hn17WRKkyKSg+5/8=\r\n-----END CERTIFICATE-----\r\n"
}
certificatePem
: Use the PEM certificate of the IACA that is being used by the issuer to sign mDocs.
Add online verification capabilities into a web application
This step is only required if you wish to implement verification capabilities. If you are only implementing holding capabilities, you can skip to step 3.
Add online verification capabilities into your web application by using the following Verifier Web SDK functions:
1. Initialize the SDK
Before using any SDK functions you must initialize the SDK by calling the initialise function:
MATTRVerifierSDK.initialise({ apiBaseUrl })
apiBaseUrl
should be replaced with the tenant_url
of your MATTR VII verifier tenant, provided
with your access credentials.
2. Create a new credential query
const credentialQuery = [
{
profile: 'mobile',
docType: 'org.iso.18013.5.1.mDL',
nameSpaces: {
'org.iso.18013.5.1': {
birthdate: {
intentToRetain: false
},
portrait: {
intentToRetain: false
},
resident_postal_code: {
intentToRetain: true
}
}
}
}
]
-
profile
: Credential format of the credential that will be verified. Currently onlymobile
(mDocs) is supported. -
docType
: the mDL’s type. Confirm with the certificate issuer for what docType they are issuing. Some common examples include:- Mobile Driver License (
org.iso.18013.5.1.mDL
). - PhotoID (
org.iso.23220.photoid.1
). - Mobile Vehicle Registration Card (
org.iso.7367.1.mVRC
). - Health certificate (
org.micov.vtr.1
).
- Mobile Driver License (
-
nameSpaces
: Each namespace corresponds to a group of claims included in the credential. These can be claims that are part of a specific standard, jurisdiction or any other reference. The namespace would usually correspond to the requesteddocType
.intentToRetain
(Optional): When set totrue
, the holder will be indicated that the verifier intends to retain this claim beyond the verification workflow. Defaults tofalse
when not specified.
In this example the credentialQuery
query will request for the birthdate
, portrait
and
resident_postal_code
claims from any credentials whose profile
is mobile
and docType
is
org.iso.18013.5.1.mDL
.
It also sets intentToRetain
as true
for the resident postal code, indicating to the holder that
the verifier will retain this claim beyond the verification workflow. The other two claims have
intentToRetain
as false
indicating that the verifier will not retain any of these claims.
While intentToRetain
defaults to false
, it is explicitly set to false
for birthdate
and
portrait
in the example above for clarity purposes. If there is no intention to retain a
claim, it is sufficient to simply exclude intentToRetain
from the query.
3. Trigger a presentation request and share it with the wallet
As part of a digital interaction with the user, call the
requestCredentials
function with the created credential query. This will trigger the configured MATTR VII verifier
tenant to create a presentation request and share it with the wallet:
const result = await MATTRVerifierSDK.requestCredentials({
credentialQuery: [credentialQuery],
challenge: MATTRVerifierSDK.utils.generateChallenge(), // replace with a challenge generated by the backend when applicable
walletProviderId,
mode: undefined, // auto detection base on browser user agent
redirectUri, // required fields for save device mode
crossDeviceCallback: {
// required fields for cross device mode
onComplete: (result) => {
console.info(
'<<< MATTRVerifierSDK.requestCredentials crossDeviceCallback.onComplete',
result
)
},
onFailure: (error) => {
console.info(
'<<< MATTRVerifierSDK.requestCredentials crossDeviceCallback.onFailure',
error
)
}
}
})
credentialQuery
: Use the query created above.challenge
: Create a random and unique challenge to ensure the security of the verification process by preventing replay attacks. You can use this challenge to verify the verification response from the MATTR VII tenant.walletProviderId
: This value must match one of the values configured on your MATTR VII verifier tenant in Step 1 above.mode
: When set toundefined
, the SDK will automatically choose the presentation flow based on the user agent’s browser (mobile agents will use same-device workflows while desktop agents will use cross-device workflows). You can set to eithercrossDevice
orsameDevice
to explicitly choose a presentation flow.redirectUri
: Only required for cross-device flows. Use the same value you configured on your MATTR VII verifier tenant in step 1 above.crossDeviceCallback
: Define how to handle success/failure cross device callbacks.
Integrate a backend into the verification workflow
This step is only required if you wish to adjust the workflow so that verification results are shared with a configured backend rather than directly with the frontend.
- Set
resultAvailableInFrontChannel
tofalse
when you create the verifier configuration. - Pass a random
challenge
to the web application and use it when calling therequestCredentials
function. - Retrieve the
sessionId
returned by the MATTR VII verifier tenant to your web application when verification is completed. - Make a request of the following structure to your MATTR VII verifier tenant to retrieve the complete verification results:
GET /v2/presentations/sessions/{sessionId}/result
- Validate the
challenge
included in the response to ensure it matches thechallenge
passed when creating the presentation session. - Process the verification results and pass the required information back to the web application to continue the interaction based on your business logic.
Add online presentation capabilities into a wallet application
This step is only required if you wish to implement holding capabilities. If you are only implementing verification capabilities, you can skip this step.
Add online presentation capabilities into your digital wallet application by using the following React Native Holder SDK components:
// start a new presentation session
const createPresentationSessionResult =
await wallet.credential.mobile.createOnlinePresentationSession({
authorisationRequestUri: '...'
})
if (createPresentationSessionResult.isErr()) {
// Define how to handle any errors creating a new presentation session
}
const session = createPresentationSessionResult.value
// Render the verifier information stored in `session.verifiedBy`.
// Render the list of matched mDocs for each received request stored in `session.matchedCredentials` for user to select.
// Construct and send a presentation response with the selected credentials
const sendResponseResult = await session.sendResponse({ credentialIds })
// In case of an error, you could either terminate the session or try and create a new createOnlinePresentationSession again
if (sendResponseResult.isErr()) {
await session.terminateSession()
}
authorisationRequestUri
: This should match theauthorizationEndpoint
defined in your MATTR VII verifier tenant configured in Step 1 above.