Learn how to configure an OID4VCI Pre-authorized Code flow to issue an mDoc into a digital wallet
Introduction
The OpenID4VCI specification is an open standard developed by the OpenID Foundation. It leverages the OpenID protocol to support verifiable credentials issuance and management.
In this tutorial we will configure an OID4VCI Pre-authorized Code flow and use it to issue an mDoc into a MATTR GO Hold example app, showing each step both through the MATTR Portal and via the equivalent API calls.
User experience
This is the user experience you will build in this tutorial:
- The user launches their GO Hold example app and scans a QR code received from an issuer.
- The GO Hold example app displays what credential is being offered and by what issuer.
- Once the user accepts the offer, they are required to provide a transaction code. This code is provided to the user by the issuer through a different channel (e.g. email, SMS, printed on paper).
- Once the transaction code is provided, the credential is immediately issued to the user's GO Hold example app. They can now view the credential and present it for verification.
UX considerations
- No prior authentication required: Users are not required to authenticate before the credential is issued. This simplifies the process but assumes the issuer has already verified the user prior to providing the credential offer (e.g., during login to a wallet application or service portal).
- Implicit credential acceptance: The user is not technically required to explicitly accept the credential offer. Depending on how the flow is implemented with wallet providers, the credential can be issued immediately upon scanning the QR code.
- Optional transaction code: The use of a transaction code is optional and can be omitted if not required by the issuer. In this tutorial, we include it to demonstrate how an additional layer of security can be added to the issuance workflow.
Prerequisites
- Complete the sign up form to get trial access to MATTR VII and the MATTR Portal, and then Create a tenant.
- Install the MATTR GO Hold example app by following the getting started guide.
We recommend using the MATTR VII Postman collection in this tutorial. While this isn't an explicit prerequisite it can really speed things up.
Tutorial overview
To build this user experience, the current tutorial comprises the following steps:
- Create Issuer certificates: Required to sign mDocs.
- Create an mDocs credentials configuration: Controls the content and branding of issued Credentials.
- Create and share a Credential offer: Used by digital wallets to trigger the issuance workflow.
- Claim the credential as the holder: Use your GO Hold example app to claim the offered Credential.
Tutorial steps
Create issuer certificates
In this tutorial you are going to issue an mDoc, so you need to have valid IACA.
- Log into the MATTR Portal.
- In the navigation panel on the left-hand side, expand the Platform Management menu.
- Select Certificates.
- Select the Create new button.
- Use the Type radio button to select IACA - Issuing Authority Certificate Authority.
- Use the Management method radio button to select MATTR managed.
- Use the Country dropdown list to select an issuing country.
- Select the Create button to create the IACA certificate.
The IACA is created as inactive by default. - Use the Status radio button to select Active.
- Select the Update button to activate the IACA certificate.
Step 1: Obtain a MATTR VII access token
All of the MATTR VII endpoints you will use in this tutorial are protected, so you will first need to use your tenant details to make a request of the following structure and obtain an access token:
POST https://{auth_server}/oauth/token
auth_server
: Replace with theauth_url
value from your tenant details.
{
"client_id": "F5qaeLDdbvnU9zhA0j4eHUGCHwC1bKtt",
"client_secret": "Wzc8J**********************************************************",
"audience": "learn.vii.au01.mattr.global",
"grant_type": "client_credentials"
}
- Replace
client_id
,client_secret
andaudience
with your own tenant details. - Keep
grant_type
asclient_credentials
.
Response
{
"access_token": "eyJhb********************************************************************",
"expires_in": 14400,
"token_type": "Bearer"
}
Use the returned access_token
value as a bearer token for all requests to your MATTR VII tenant in
the next steps of this tutorial.
You will need to obtain a new access token whenever it expires. We recommend using our Postman collection to interact with your MATTR VII tenant. This collection includes a pre-request script to obtain an access token when it is missing or expired, as well as pre-configured templates for all available requests.
Step 2: Create the IACA certificate
- Make the following request to your MATTR VII tenant to create an IACA:
POST /v2/credentials/mobile/iacas
The response will include an id
element which you will use in the next step.
- Make the following request to activate the IACA you just created:
PUT /v2/credentials/mobile/iacas/{iacaId}
iacaId
: Replace with theid
element returned in the response when you created the IACA in the previous steps.
{
"active": true
}
Your IACA is now active and can be used to sign mDocs.
Create a MATTR VII mDocs credential configuration
-
In the navigation panel on the left-hand side, expand the Credential Issuance menu.
-
Select Mobile credential.
-
Select the Create new button.
-
In the Name text box, enter a clear and descriptive title that will appear on the credential in the wallet, for example "My First Pre-Auth Credential".
-
In the Description text box, enter a clear and descriptive description that will appear on the credential in the wallet, for example "For High Assurance Interactions".
-
In the Credential type text box, enter a unique identifier for the credential type, for example
com.example.myfirstpreauthcredential
. -
Copy and paste the following JSON into the Claim mappings text box:
Claim mappings { "com.example.personaldetails.1": { "name": { "mapFrom": "claims.name", "type": "string" }, "email": { "mapFrom": "claims.email", "type": "string" } } }
-
Enter "1" in the Months text box in the Validity for panel to set the credential expiration period.
-
Select the Create button to create the credential configuration.
Make the following request to create a simple mDoc credentials configuration that includes the holder's name and e-mail:
POST /v2/credentials/mobile/configurations
{
"type": "com.example.myfirstpreauthcredential",
"expiresIn": {
"months": 1
},
"claimMappings": {
"com.example.personaldetails.1": {
"name": {
"mapFrom": "claims.name",
"type": "string"
},
"email": {
"mapFrom": "claims.email",
"type": "string"
}
}
},
"branding": {
"name": "My First Pre-Auth Credential",
"description": "For High Assurance Interactions",
"backgroundColor": "#a2d82dff"
},
"includeStatus": true
}
The response will include an id
element. You will use it to create a Credential offer in the next
step.
Create a Credential offer
You now have all the pieces in place and can wrap them all together to generate a Credential offer and share it with the intended holder so that they know what credentials are being offered and by whom.
Make the following request to generate a new Pre-authorized Code flow Credential offer:
POST /v1/openid/offers/pre-authorized
{
"credentials": ["707e920a-f342-443b-ae24-6946b7b5033e"],
"transactionCodeConfiguration": {
"inputMode": "numeric",
"description": "Please enter the one-time code that was sent to you via email."
},
"claims": {
"name": "John Doe",
"email": "john.doe@example.com"
},
"expiresIn": {
"minutes": 10
}
}
credentials
: Populate the array with theid
element returned in the response when you created an mDocs credentials configuration in the previous step.
In this example, the claims are included directly in the credential offer. This is allowed in the Pre-authorized Code flow because the user's identity has already been verified. You can provide these claims programmatically when creating the credential offer, or you can reference a Claims source in your credential configuration to dynamically populate the claims in the issued credential.
Response
{
"id": "e6e5e43c-8053-464a-aca4-ca43da765c97",
"uri": "openid-credential-offer://?credential_offer=%7B%22credential_issuer%22%3A%22https%3A%2F%2Flearn.vii.au01.mattr.global%22%2C%22credentials%22%3A%5B%22b7b380be-1467-446b-8683-1d131e6532be%22%5D%2C%22grants%22%3A%7B%22urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Apre-authorized_code%22%3A%7B%22pre-authorized_code%22%3A%229K3N9UPQD-Hs5f5-gPx0fRJEmb1XTZsWszzXL024pV0%22%2C%22tx_code%22%3A%7B%22length%22%3A6%2C%22input_mode%22%3A%22numeric%22%2C%22description%22%3A%22Please%20enter%20the%20one-time%20code%20that%20was%20sent%20to%20you%20via%20email.%22%7D%7D%7D%7D",
"userId": "6e30dd69-c867-4279-afd3-e6619253b4a4",
"expiresAt": "2025-08-25T01:39:00.523Z",
"transactionCode": "763677"
}
You will need to obtain two important elements from the response:
transactionCode
: This is the one-time code that the user will need to provide in order to claim the credential. In production deployments you will need to provide it to the user through a different channel (e.g., email, SMS, printed on paper).uri
: This URI can be used by a digital wallet to trigger the OID4VCI workflow. Use one of the following tools to convert theuri
value to a QR code (make sure you use thePlain text
option where available) and save the generated QR code as an image file.
MATTR is not affiliated with any of these service providers and cannot vouch for their offerings.
Use the MATTR GO Hold example app to claim the credential
- Open the GO hold example app.
- Select Scan.
- Scan the QR code generated in the previous step.
- Review the credential offer and select Accept.
- Provide the transaction code provided when you created the credential offer.
- Follow the on-screen instructions to claim the credential.
Congratulations, you just configured an end-to-end OID4VCI Pre-authorized Code flow to issue an mDoc into a digital wallet!!!
What's next?
In this tutorial we have configured a basic OID4VCI Pre-authorized Code flow. However, you can use MATTR VII to create more complex and rich issuance experience. Check out more resources on MATTR Learn that will enable you to:
- Experiment with a different issuance flow by completing the OID4VCI Authorization Code flow tutorial.
- Configure a Claims source to retrieve data from compatible data sources and use it in the issued credential.
- Apply branding to issued credentials as part of creating a Credential configuration.
How would you rate this page?