light-mode-image
Learn
Claims source

Learn how to integrate a claims source into an OID4VCI workflow

Introduction

In an OpenID4VCI issuance workflow, you can enhance the credential issuance process by configuring your tenant to fetch claims directly from a compatible Claims source. These claims can then be used to issue verifiable credentials tailored to the user's data.

Claim sources can be integrated both to OID4VCI Authorization Code and Pre-authorized Code flows.

This tutorial walks you through setting up an OID4VCI workflow that issues an ISO-compliant mobile Driving Licence (mDL) by integrating a claims source to retrieve the holder's address and driving privilege information at issuance time. The holder's driver's licence number is used as the query parameter to look up their record in the claims source—mirroring how a real-world issuer would query a DMV or licensing authority database. The tutorial shows you how to achieve this using both the MATTR Portal and the MATTR VII Platform API.

Prerequisites

  • Ensure you have completed either the Authorization Code or Pre-authorized Code tutorials, as the claims source tutorial builds upon them.
  • Download the sample Claims source application, which will be used to simulate a claims source.
  • To test locally you will need to expose your local claims source to the internet. You can do this by setting up a free ngrok account, using a Cloudflare tunnel or using your own solution. For this tutorial we will be using ngrok. Sign up for a free account at ngrok.com.

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

The current tutorial builds upon the Authorization Code or Pre-authorized Code tutorials by adding the following steps:

  1. Set up a local Claims source: Use the provided sample Node.js application to simulate a claims source by providing a REST API to retrieve claims for specific users.
  2. Integrate the Claims source with MATTR VII: Configure MATTR VII to connect to and utilize the sample Claims source for retrieving claims during an OID4VCI workflow.

The following diagram illustrates how a claims source fits into the OID4VCI issuance workflow:

The workflow proceeds as follows:

  1. Initiate issuance: The wallet triggers an OID4VCI issuance workflow — either an Authorization Code or Pre-authorized Code flow. During this stage, claims may be gathered from an Authentication Provider and/or an Interaction Hook.
  2. Resolve claims source: MATTR VII reads the credential configuration referenced in the credential offer and identifies the configured claims source.
  3. Authorize the request: MATTR VII authenticates with the claims source using the configured authorization method:
    • OAuth Client Credentials — MATTR VII requests a Bearer access token from the authorization server and uses it as an Authorization header.
    • API Key — MATTR VII passes the configured key as an x-api-key header.
  4. Fetch claims: MATTR VII sends an HTTP request (GET or POST) to the claims source endpoint, including any configured request parameters — these can be dynamic (mapped from available claims or credential configuration data) or static.
  5. Return claims: The claims source must respond within three seconds with a 2XX status code and a valid JSON object containing the claims to be used in the credential. An empty object is returned if no claims are found.
  6. Map and issue: MATTR VII maps the returned claims according to the credential configuration and generates the signed credential, which is delivered to the wallet.

Tutorial steps

Set up a local Claims source

  1. Clone the MATTR Sample Apps repo to your machine and navigate to the claims-source-app folder.

  2. Rename the env-example file to .env.

  3. Change the value of NGROK_AUTHTOKEN to your ngrok authentication token.

  4. Open the database.json file and add a new object to represent a user with their mDL record:

    • Set the licenseNumber value (for example, DL-123456). This is the driver's licence number that will be used as the query parameter when looking up the user's record in the claims source.
      • If you are building on top of the Authorization Code flow tutorial, the same value must exist as a property for the authenticated user in your Auth0 application.
      • If you are building on top of the Pre-authorized Code flow tutorial, you can use any value, but make note of it as you will need it later when you create the credential offer.
    • Populate the following mDL address fields with realistic test values:
      • resident_address — street address (for example, 123 Main Street)
      • resident_city — city (for example, Springfield)
      • resident_state — state or region code (for example, IL)
      • resident_postal_code — postal code (for example, 62701)
  5. Start the claims source app either via npm or docker:

    Start via npm
    npm install
    npm run dev

    or

    Start via docker
    docker compose up --build
  6. Make note of the Public Claims Source URL displayed in the terminal after starting the app. This URL will be used to configure the Claims source in your MATTR VII tenant.

Your claims source is now set up and ready to be used. The provided application meets the requirements for integrating a claims source into a MATTR VII OID4VCI workflow, and will return the holder's resident address details when queried with their driver's licence number.

Next, we will configure MATTR VII to connect to this claims source.

Configure the Claims source in your MATTR VII tenant

This step can be achieved either via the MATTR Portal or the MATTR VII Platform APIs.

  1. In the navigation panel on the left-hand side, expand the Credential Issuance menu.

  2. Select Claims sources.

  3. Click the Create new button.

  4. Insert a meaningful name for your Claims source in the Name field. For example, "DMV Claims source".

  5. In the URL field, paste the Public Claims Source URL generated when you started the claims source application.

  6. In the Authorization type section, select API Key as the type.

  7. In the API Key field, paste supersecretapikey. This is the API key used by the sample claims source application to control access. In Production environments, it is strongly recommended to use a more secure API key.

  8. Paste the following code into the Request parameters field:

    Request parameters
    {
        "licenseNumber": {
            "mapFrom": "claims.licenseNumber"
        }
    }

    This maps the holder's driver's licence number to a query parameter that will be sent to the claims source to look up their mDL record.

    • In Authorization code flows the licenseNumber claim must be provided by the Authentication provider. It can be retrieved from the authenticated user's identity in an Interaction hook and added to the claim set that is returned to MATTR VII, or it can be included in the ID token claims by the Authentication provider (e.g., Auth0) and mapped in the credential configuration.
    • In Pre-authorized code flows it is provided by the issuer as part of the credential offer. In this case, you would map it from the credential offer claims in the same way as shown above.
  9. Select Create to create the Claims source.

Make a request of the following structure to configure a new claims source:

Request
POST /v1/claim-sources
Request body
{
    "name": "DMV Claims source",
    "url": "<CLAIM_SOURCE_URL>", 
    "authorization": { 
        "type": "api-key", 
        "value": "supersecretapikey"
    },
    "requestMethod": "GET",
    "requestParameters": { 
        "licenseNumber": { 
            "mapFrom": "claims.licenseNumber"
        } 
    }
}
  • url : Replace this with the Public Claims Source URL generated when you started the claims source application. The URL should follow this format: https://<YOUR_NGROK_SUBDOMAIN>/claims.
  • authorization : Specifies how to access the claims source. The sample claims source application uses an API key (supersecretapikey) for access control. For production environments, it is strongly recommended to use a more secure API key.
  • requestParameters : Maps the holder's driver's licence number to a licenseNumber query parameter. MATTR VII sends this parameter to the claims source to look up the holder's mDL record, returning their resident address and other mDL fields.
    • In Authorization code flows the licenseNumber claim must be provided by the Authentication provider. It can be retrieved from the authenticated user's identity in an Interaction hook and added to the claim set that is returned to MATTR VII, or it can be included in the ID token claims by the Authentication provider (e.g., Auth0) and mapped in the credential configuration.
    • In Pre-authorized code flows it is provided by the issuer as part of the credential offer. In this case, you would map it from the credential offer claims in the same way as shown above.

Response

Response body
{
    "id": "945214ad-3635-4aff-b51d-61d69a3c8eee"
    // Remaining response properties
}
  • id : Unique identifier for the configured Claims source. We will use it in the next step to integrate the Claims source into the OID4VCI workflow.

Use the Claim source in a credential configuration

This step can be achieved either via the MATTR Portal or the MATTR VII Platform APIs.

  1. In the navigation panel on the left-hand side, expand the Credential Issuance menu.

  2. Select mDocs.

  3. Select the Create new button.

  4. In the Name text box, enter a clear and descriptive title that will appear on the credential in the wallet, for example "Mobile Driving Licence".

  5. In the Description text box, enter a clear and descriptive description that will appear on the credential in the wallet, for example "ISO 18013-5 compliant mDL".

  6. In the Credential type text box, enter org.iso.18013.5.1.mDL.

  7. Paste the following JSON into the Claim mappings text box:

    Claim mappings
    {
        "org.iso.18013.5.1": {
            "family_name": {
                "mapFrom": "claims.family_name",
                "type": "string"
            },
            "given_name": {
                "mapFrom": "claims.given_name",
                "type": "string"
            },
            "document_number": {
                "mapFrom": "claims.licenseNumber",
                "type": "string"
            },
            "resident_address": {
                "mapFrom": "claims.resident_address",
                "type": "string"
            },
            "resident_city": {
                "mapFrom": "claims.resident_city",
                "type": "string"
            },
            "resident_state": {
                "mapFrom": "claims.resident_state",
                "type": "string"
            },
            "resident_postal_code": {
                "mapFrom": "claims.resident_postal_code",
                "type": "string"
            }
        }
    }

    The address claims (resident_address, resident_city, resident_state, resident_postal_code) will be retrieved from the Claims source configured in the previous step. The identity claims (family_name, given_name) will be retrieved from the authentication provider (e.g., Auth0), and document_number is mapped from the licenseNumber claim.

    Note that a compliant mDL credential has specific requirements for the claims it includes. In this tutorial we are including the resident_address, resident_city, resident_state and resident_postal_code claims from the Claims source, and the family_name, given_name and document_number claims from the authentication provider, to demonstrate how to map claims from multiple sources to meet these requirements.

  8. Use the Claim source dropdown to select the Claims source you created in the previous step. This will allow the credential to retrieve claims from the configured Claims source during issuance.

  9. Enter "1" in the Months text box in the Validity for panel to set the credential expiration period.

  10. Select the Create button to create the credential configuration.

Make the following request to create an ISO 18013-5 compliant mDoc credentials configuration that includes the holder's identity claims from the authentication provider, and their resident address retrieved from your configured Claims source:

Request
POST /v2/credentials/mobile/configurations
Request body
{
    "type": "org.iso.18013.5.1.mDL",
    "expiresIn": {
        "months": 1
    },
    "claimMappings": {
        "org.iso.18013.5.1": {
            "family_name": {
                "mapFrom": "claims.family_name",
                "type": "string"
            },
            "given_name": {
                "mapFrom": "claims.given_name",
                "type": "string"
            },
            "document_number": {
                "mapFrom": "claims.licenseNumber",
                "type": "string"
            },
            "resident_address": { 
                "mapFrom": "claims.resident_address", 
                "type": "string"
            }, 
            "resident_city": { 
                "mapFrom": "claims.resident_city", 
                "type": "string"
            }, 
            "resident_state": { 
                "mapFrom": "claims.resident_state", 
                "type": "string"
            }, 
            "resident_postal_code": { 
                "mapFrom": "claims.resident_postal_code", 
                "type": "string"
            } 
        }
    },
    "branding": {
        "name": "Mobile Driving Licence",
        "description": "ISO 18013-5 compliant mDL",
        "backgroundColor": "#1a3a5cff"
    },
    "claimSourceId": "<CLAIM_SOURCE_ID>", 
    "includeStatus": true
}
  • resident_address, resident_city, resident_state, resident_postal_code : These claims represent the holder's residential address. They are retrieved from the Claims source using the holder's licenseNumber as the lookup key, and stored in the claims object. During credential issuance they are mapped into the org.iso.18013.5.1 namespace of the mDL. Note that a compliant mDL credential has specific requirements for the claims it includes. In this tutorial we are including the resident_address, resident_city, resident_state and resident_postal_code claims from the Claims source, and the family_name, given_name and document_number claims from the authentication provider, to demonstrate how to map claims from multiple sources to meet these requirements.
  • claimSourceId : Replace this with the id value returned in the response when you configured the Claims source in the previous step.

Response

Response body
{
    "id": "294868aa-3814-4a50-9862-5ff48381a8e5"
    //... rest of your credential configuration
}
  • id : Unique identifier for the created mDocs credentials configuration. This ID is used 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.

Make sure you create a credential offer that matches the flow you are implementing.

Creating pre-authorized code flow credential offers in the MATTR Portal is for testing purposes only. The populated user ID is generated by the MATTR Portal and cannot be changed to another user later.

  1. In the navigation panel on the left-hand side, expand the Credential Issuance menu.
  2. Select Credential offer.
  3. Use the Workflow radio button to select Pre-authorized code flow.
  4. Select the Select button.
  5. Check the checkbox next to the credential configuration you created in the previous step.
  6. Select the Apply button.
  7. In the Claims panel, select Add new and add a claim with the following details:
  8. Select the Generate button.
  9. Copy the Transaction code that is displayed on the screen.
    In production deployments you will need to provide it to the user through a different channel (e.g., email, SMS).
  10. Download the displayed QR code.
    This QR code will be used by the holder to claim the credential.

Make the following request to generate a new Pre-authorized Code flow Credential offer:

Request
POST /v1/openid/offers/pre-authorized
Request body
{
    "credentials": ["707e920a-f342-443b-ae24-6946b7b5033e"], 
    "transactionCodeConfiguration": {
        "inputMode": "numeric",
        "description": "Please enter the one-time code that was sent to you."
    },
    "claims": {
        "family_name": "Doe",
        "given_name": "Jane",
        "licenseNumber": "<DRIVER_LICENSE_NUMBER>"
    },
    "expiresIn": {
        "minutes": 10
    }
}
  • credentials : Populate the array with the id element returned in the response when you created an mDocs credentials configuration in the previous step.
  • licenseNumber : Replace <DRIVER_LICENSE_NUMBER> with the driver's licence number you used when you set up your local claims source (for example, DL-123456). MATTR VII will use this value to query the claims source and retrieve the holder's resident address.

In this example we are manually inserting the driver's licence number into the credential offer request. In a real-world scenario, you would want to dynamically populate this value based on the authenticated user's identity, for example by retrieving it from your identity store.

Response

Response body
{
    "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).
  • uri : This URI can be used by a digital wallet to trigger the OID4VCI workflow. Use one of the following tools to convert the uri value to a QR code (make sure you use the Plain 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.

  1. In the navigation panel on the left-hand side, expand the Credential Issuance menu.
  2. Select Credential offer.
  3. Select the Select button.
  4. Check the checkbox next to the credential configuration you created in the previous step.
  5. Select the Apply button.
  6. Select the Generate button.
  7. Download the generated QR code by selecting the Download button.

Make the following request to generate a new Credential offer:

Request
POST /v1/openid/offers
Request body
{
    "credentials": ["<CREDENTIAL_CONFIGURATION_ID>"]
}
  • credentials: Replace this with the id value returned in the response when you created the mDocs credentials configuration in the previous step.

Response

The response will include a uri element which can be used by a digital wallet to trigger the OID4VCI workflow. Use one of the following tools to convert the uri value to a QR code (make sure you use the Plain text option where available):

MATTR is not affiliated with any of these service providers and cannot vouch for their offerings.

Save the generated QR code on your computer.

Test the workflow

  1. Open the GO hold example app.
  2. Select Scan.
  3. Scan the QR code generated in the previous step.
  4. Review the credential offer and select Accept.
  5. Follow the issuance workflow instructions to claim the credential.

You should now see an mDL in your wallet that includes the holder's resident address (resident_address, resident_city, resident_state, resident_postal_code), which was retrieved from your configured Claims source. MATTR VII obtained these claims by querying the Claims source using the holder's driver's licence number as a query parameter—either supplied by the authentication provider (Authorization Code flow) or specified in the credential offer (Pre-authorized Code flow).

What's next?

Check out more resources on MATTR Learn that will enable you to:

How would you rate this page?

Last updated on

On this page