light-mode-image
Learn

In-person verification quickstart guide

This quickstart is for evaluating the MATTR Pi mDocs Verifier SDKs for in-person verification. In about 10 minutes you will configure a sample verifier mobile app (iOS, Android, or React Native), run it on a test device and use it to verify an mDoc presented in-person from a different device using the proximity presentation workflow defined by ISO/IEC 18013-5:2021.

Use this guide as a fast evaluation path to see the Verifier Mobile SDK working end-to-end on real devices. For detailed information and API examples, explore the tutorial and reference documentation tailored for each platform.

User experience

In this quickstart you will perform this exact flow yourself using the sample verifier app and the GO Hold example app:

Tutorial Workflow

  1. The holder uses their wallet application to generate and present a QR code.
  2. The verifier scans the QR code, connects with the wallet, and requests an mDoc for verification.
  3. The wallet application displays matching credentials to the holder and asks for consent to share them with the verifier.
  4. The verifier application receives the wallet's response and verifies the provided credential.
  5. Verification results are displayed to the verifier.

Prerequisites

  • Access to the MATTR Pi mDocs Verifier SDK for your chosen platform (iOS, Android, or React Native). Apply for access here.
  • Two physical mobile devices to run the verifier and holder applications:
    • Verifier device: iOS/Android mobile device to run the built Verifier application on, set up with Bluetooth access.
    • Holder device: iOS/Android mobile device with the MATTR GO Hold example app installed for iOS or Android, set up with biometric authentication and Bluetooth access.
  • Development environment set up for your chosen platform (e.g., Xcode for iOS, Android Studio for Android, or a React Native development environment).

Steps

In this quickstart you will:

  1. Configure a local sample verifier project for your platform.
  2. Run a sample verifier app and verify a credential presented in-person from a holder device.
  3. Review the structure of the sample project so you can see how to integrate the SDK into your own app.

Use the tabs below to follow platform-specific setup steps.

Configure the sample verifier project (5-10 Minutes)

  1. Download and unzip the sample iOS proximity verifier project.
  2. Use Xcode to open the .xcodeproj file in the unzipped folder.
  3. Drag the MobileCredentialVerifierSDK-*version*.xcframework folder (obtained from MATTR as part of the SDK package) into your project.
  4. Configure MobileCredentialVerifierSDK-*version*.xcframework to Embed & sign.
  5. Set a unique bundle identifier for the project in the Xcode project settings (e.g., com.yourname.proximityverifier).
  6. Run the project on a physical iOS device (simulators do not support the required Bluetooth capabilities).
  1. Download and unzip the sample Android proximity verifier project.
  2. Open the project in Android Studio.
  3. Unzip the mobile-credential-verifier-*version*.zip file (obtained from MATTR as part of the SDK package).
  4. Drag the unzipped global folder into the project's repo folder.
  5. Sync Project with Gradle files to recognize the new module.
  6. Run the project on a physical Android device (emulators do not support the required Bluetooth capabilities).
  1. Access the completed sample verifier codebase by either:

    • Cloning the MATTR sample-apps repository:

      Clone the repository
      git clone https://github.com/mattrglobal/sample-apps.git

      or

    • Downloading just the relevant directory using the download-directory.github.io utility.

  2. Open the completed sample verifier project in your code editor. You can find it in the sample-apps/react-native-mdocs-verifier-tutorial/react-native-mdocs-verifier-tutorial-complete directory.

  3. Open the app.config.ts file.

  4. Update the iOS bundleIdentifier to a unique value for your application, e.g. com.mycompany.myapp.

    app.config.ts
    bundleIdentifier: "com.mycompany.myapp",
  5. Update the Android package to a unique value, e.g. com.mycompany.myapp:

    app.config.ts
    package: "com.mycompany.myapp",
  6. Navigate to the starter project directory and install dependencies:

    Install dependencies
    yarn install

You must be logged in to npm with access to the MATTR Pi mDocs Verifier SDK package to install dependencies successfully. If you have not yet been granted access to the SDK, apply for access here.

  1. Run the following command to generate the iOS and Android project files:

    Generate project files
    yarn expo prebuild

You should now see the ios and android folders in your project root.

  1. Connect your testing device(s) and run the following command(s) to start the application(s):

iOS

Run iOS application
yarn ios --device

Android

Run Android application
yarn android --device

Verify a credential using the sample verifier app (3 Minutes)

  1. On your holder testing device, launch the GO Hold example app.
  2. Tap the Blue Share button.
  3. Select Respond or Collect. This will open the camera view (You may need to allow the app to access your camera).
  4. Scan the following QR code:

QR Code

  1. Follow the on-screen instructions to claim the credential (Note that this workflow requires an active internet connection).
  2. Once the credential is claimed, select the Blue Share button again.
  3. Select Share Credential and then choose the Connection QR tab to display a QR code.
  4. On your verifier testing device, launch the sample verifier app and select the Scan QR Code button.
  5. Use the verifier testing device to scan the QR code displayed on the holder testing device.
  6. On your holder testing device, consent to sharing the information with the verifier.
  7. On your verifier testing device, review the verification results displayed in the app.

Behind the scenes, the Verifier Mobile SDK handles device engagement, secure session establishment, and verification of the mDoc according to ISO/IEC 18013-5:2021.

Review the codebase

The sample verifier application uses the Verifier Mobile SDK to verify mDocs presented in-person from a wallet. Once you have the sample application running, use this section to inspect the key SDK calls you will reuse in your own application.

The sample projects include code comments that explain the purpose of each step and how it maps to the in-person verification workflow. The key steps for handling in-person verification with the SDK are outlined below, along with links to the relevant API reference documentation for each platform.

Initialize the SDK

In the sample app, SDK initialization happens once during startup so the verifier can handle in-person sessions.

Initialize the SDK
mobileCredentialVerifier.initialize()
Initialize the SDK
MobileCredentialVerifier.initialize(activity)
Initialize the SDK
const result = await initialize();
if (result.isErr()) {
  // Handle error: result.error
}

Adding a trusted issuer certificate

In the sample app, a trusted issuer certificate is added during startup after SDK initialization. This allows the verifier to validate the authenticity of credentials issued by trusted issuers.

Add a trusted issuer certificate
try await mobileCredentialVerifier.addTrustedIssuerCertificates(certificates: [certificate])
  • certificate : Pass the IACA certificate of an issuer you want your application to trust.
Add a trusted issuer certificate
MobileCredentialVerifier.addTrustedIssuerCertificates(certificates = listOf(certificate))
  • certificate : Pass the IACA certificate of an issuer you want your application to trust.
Add a trusted issuer certificate
await mobileCredentialVerifier.addTrustedIssuerCertificates([certificate])
  • certificate : Pass the IACA certificate of an issuer you want your application to trust.

Create a presentation request object

Before sending a presentation request to the holder, the verifier application needs to create a request object that defines the type of credential and specific attributes being requested for verification.

Create a presentation request
    let mobileCredentialRequest = MobileCredentialRequest(
        docType: "<DocType>",
        namespaces: [
            "<Namespace>": [
                "<AttributeName1>": false,
                "<AttributeName2>": false,
                "<AttributeName3>": false
            ]
        ]
    )
  • docType : The type of credential being requested (e.g., an mDL).
  • namespaces : A dictionary mapping each namespace to its requested attributes. Each attribute is a key with a Boolean indicating whether the verifier intends to retain this attribute (true) or not (false).
Create a presentation request
val mobileCredentialRequest = MobileCredentialRequest(
    docType = "<DocType>",
    namespaces = NameSpaces(
        mapOf(
            "<Namespace>" to DataElements(
                mapOf(
                    "<AttributeName1>" to false,
                    "<AttributeName2>" to false,
                    "<AttributeName3>" to false
                )
            )
        )
    )
)
  • docType : The type of credential being requested (e.g., an mDL).
  • namespaces : A map of requested attributes under each namespace, where false indicates the verifier does not intent to retain this attribute.
Create a presentation request
const mobileCredentialRequest = {
    docType: '<DocType>',
    namespaces: {
        '<Namespace>': {
            '<AttributeName1>': false,
            '<AttributeName2>': false,
            '<AttributeName3>': false
        }
    }
}
  • docType : The type of credential being requested (e.g., an mDL).
  • namespaces : An object that defines the attributes being requested for each namespace. A value of false indicates the verifier does not intent to retain this attribute.

Create a proximity presentation session

Once the verifier application receives a device engagement string (e.g., from scanning a QR code presented by the holder), it can create a proximity presentation session to establish a secure connection with the holder's wallet and send presentation requests.

  1. Extend a class with the ProximityPresentationSessionListener protocol:
Conform to ProximityPresentationSessionListener
extension VerifierViewModel: ProximityPresentationSessionListener {
  public func onEstablished() {
    // Handle session establishment: show presentation session details or send a request.
  }
  public func onTerminated(error: (any Error)?) {
    /// Handle session termination
    print("Session Terminated")
  }
}
  1. Call the createProximityPresentationSession function with an instance of the extended class:
Create a proximity presentation session
mobileCredentialVerifier.createProximityPresentationSession(encodedDeviceEngagementString: deviceEngagementString, listener: self)
  • encodedDeviceEngagementString : Pass the device engagement string retrieved from a QR code presented by the holder.
  • listener : An object that conforms to ProximityPresentationSessionListener protocol and will handle the session events.
  1. Implement the ProximityPresentationSessionListener interface:
Implement ProximityPresentationSessionListener
val sessionListener = object : ProximityPresentationSessionListener {
    override fun onEstablished() {
        // Handle session establishment: show presentation session details or send a request.
    }

    override fun onTerminated(error: Throwable?) {
        Log.d("SessionListener", "Session Terminated")
    }
}
  1. Call the createProximityPresentationSession function with an instance of the extended class:
Create a proximity presentation session
MobileCredentialVerifier.createProximityPresentationSession(activity, deviceEngagementString, sessionListener)
  • deviceEngagementString : Pass the device engagement string retrieved from a QR code presented by the holder.
  • sessionListener : An object that implements ProximityPresentationSessionListener interface and will handle the session events.
Create a proximity presentation session
const proximityPresentationSession =
    await mobileCredentialVerifier.createProximityPresentationSession({
        encodedDeviceEngagementString: encodedDeviceEngagementString,
        onSessionTerminated: (error) => {
            // Handle session termination or error
        }
    })
  • encodedDeviceEngagementString : Pass the device engagement string retrieved from a QR code presented by the holder.
  • onSessionTerminated : A callback triggered when the session ends or fails.

The createProximityPresentationSession method returns an empty success response, indicating that the session has been created and the verifier application can send a presentation request to the holder.

Listen to NFC session requests

To support NFC-based device engagement in addition to QR code scanning, the verifier application can listen for NFC session requests. When an NFC session request is received, the SDK will automatically create a proximity presentation session and trigger the appropriate session listener callbacks.

This capability is currently only available in the Android SDK.

Start listening to NFC session requests
MobileCredentialVerifier.registerForNfcDeviceEngagement(activity, sessionListener)
  • sessionListener : An object that implements the ProximityPresentationSessionListener interface and will handle the session events.

    Stop listening to NFC session requests
    MobileCredentialVerifier.deregisterForNfcDeviceEngagement(activity)

This capability is currently only available in the Android SDK.

Send a presentation request

After a proximity presentation session is established (e.g., after scanning a QR code or receiving an NFC engagement), the verifier application can send a presentation request to the holder's wallet to request specific credentials for verification.

Send a presentation request
try await mobileCredentialVerifier.sendProximityPresentationRequest(request: [mobileCredentialRequest], checkStatus: true)
  • request : Pass the MobileCredentialRequest object created in the previous step.
  • checkStatus : A Boolean indicating whether to check credential revocation status. Set to true (default) to check credential revocation status as part of the verification, or false to skip status checking.
Send a presentation request
MobileCredentialVerifier.sendProximityPresentationRequest(request = listOf(mobileCredentialRequest), checkStatus = true)
  • request : Pass the MobileCredentialRequest object created in the previous step.
  • checkStatus : A Boolean indicating whether to check credential revocation status. Set to true (default) to check credential revocation status as part of the verification, or false to skip status checking.
Send a presentation request
const mobileCredentialResponse =
    await proximityPresentationSession.sendProximityPresentationRequest({
        request: mobileCredentialRequest,
        checkStatus: true
    })
  • request : Pass the MobileCredentialRequest object created two steps up.
  • checkStatus : A Boolean indicating whether to check credential revocation status. Set to true (default) to check credential revocation status as part of the verification, or false to skip status checking.

Handle the presentation response

After sending a presentation request, the verifier application will receive a response from the holder's wallet containing the credentials that match the request along with their verification status. The application can then handle this response to display verification results to the user.

The requestMobileCredentials method returns a MobileCredentialResponse object. This response contains the presentation details provided by the holder, including any errors encountered and the verification status of the credentials returned in the response:

MobileCredentialResponse
let mobileCredentialResponse = MobileCredentialResponse(
    credentialErrors: [/* CredentialError */],
    credentials: [
        MobileCredentialPresentation(
            branding: /* Branding information for displaying the credential */,
            claimErrors: [
                /* Namespace */: [
                    /* ElementID */: /* MobileCredentialResponseErrorCode */
                ]
            ],
            claims: [
                /* Namespace */: [
                    /* ElementID */: /* MobileCredentialElementValue */
                ]
            ],
            docType: /* DocType */,
            issuerInfo: /* IssuerInfo */,
            validityInfo: /* Validity */,
            verificationResult: /* VerificationResult */
        )
    ]
)
  • credentialErrors : Any requested docTypes not returned by the holder.
  • credentials : A list of presented credentials with their data, status, and any attribute-specific errors.

The sendProximityPresentationRequest method returns a MobileCredentialResponse object. This response contains the presentation details provided by the holder, including any errors encountered and the verification status of the credentials returned in the response:

MobileCredentialResponse structure
data class MobileCredentialResponse(
    val credentials: List<MobileCredentialPresentation>?,
    val credentialErrors: List<CredentialError>?
)
MobileCredentialPresentation structure
data class MobileCredentialPresentation(
    val docType: DocType,
    val validityInfo: MobileCredentialValidity,
    val claimErrors: Map<NameSpace, Map<DataElementIdentifier, ErrorCode>>?,
    val claims: Map<NameSpace, Map<DataElementIdentifier, MobileCredentialElement>>?,
    val branding: Branding?,
    val issuerInfo: IssuerInfo?,
    val verificationResult: MobileCredentialVerificationResult
)
CredentialError structure
data class CredentialError(
    val docType: DocType,
    val errorCode: ErrorCode
)

typealias DocType = String
typealias ErrorCode = Int
  • credentialErrors : Any requested docTypes not returned by the holder.
  • credentials : A list of presented credentials with their data, status, and any attribute-specific errors.

The sendProximityPresentationRequest returns a MobileCredentialResponse object. This response contains the presentation details provided by the holder, including any errors encountered and the verification status of the credentials returned in the response:

MobileCredentialResponse
const mobileCredentialResponse = {
  credentialErrors: [/* CredentialError */],
  credentials: [
    {
      branding: /* Branding */,
      claimErrors: {
        /* Namespace */: {
          /* ElementID */: /* MobileCredentialResponseErrorCode */
        }
      },
      claims: {
        /* Namespace */: {
          /* ElementID */: /* MobileCredentialElementValue */
        }
      },
      docType: /* DocType */,
      issuerInfo: /* IssuerInfo */,
      validityInfo: /* Validity */,
      verificationResult: /* VerificationResult */
    }
  ]
};
  • credentialErrors : Any requested docTypes not returned by the holder.
  • credentials : A list of presented credentials with their data, status, and any attribute-specific errors.

Next steps

  • For your evaluation:
    • Note how long it took to configure and run the sample verifier app and complete an in-person verification.
    • Consider how the sample’s presentation request and UI map to your real in-person verification use cases (for example, which attributes you would request and how you would display them).
  • Explore the in-person verification tutorial for detailed instructions, configuration options, and production-grade patterns.
  • Review the mDocs Verifier SDK overview to understand platform support, capabilities, and how proximity and remote verification relate.

How would you rate this page?

Last updated on

On this page