MATTR Verifier SDK React Native - v5.0.0

MATTR Verifier SDK React Native

Table of Contents

General

Licensing

Request or download the MATTR Pi SDK Trial Licence Agreement and the MATTR Customer Agreement and review these terms.

Features

  • Verify CWT credentials and mDocs.
  • Refresh cached revocation lists and trusted issuers list.
  • Get the expiry date of the most-soon-to-expire item in the cache.
  • Check the status of presented mDocs.

In this SDK mDocs are referred to as Mobile credentials and CWT credentials are referred to as Compact credentials.

Supported operating systems

  • iOS 15 or higher.
  • Android 7 or higher.

Getting started

How to get access to MATTR Pi Verifier SDK

Refer to our SDK Docs landing page for step-by-step instructions to gain access to any of our SDKs.

Please reach out to us in case you need any assistance.

Install dependencies

Add this SDK as a dependency to the react native app:

yarn add @mattrglobal/verifier-sdk-react-native

The SDK relies on a set of peer dependencies that contain native libraries.

Install the peer dependencies:

we recommend to use react-native-mmkv <= 2.11.0. MMKV >2.11.X uses a bad underlying MMKV version. For more information see https://github.com/mrousavy/react-native-mmkv/issues/707

yarn add @mattrglobal/react-native-cryptography@^2.1.1 react-native-file-access@^3.1.1 react-native-get-random-values@^1.11.0 react-native-mmkv@2.11.0

This SDK can be used in the same application with the following versions of the mobile-credential-holder-react-native SDK:

  • 4.0.0

we tested with react-native 0.73.10

Usage

Verifier

Create a verifier:

import { init } from "@mattrglobal/verifier-sdk-react-native";

const initOptions: InitOptions = {
issuerCacheTtl: 60000,
revocationListCacheTtl: 60000,
trustedIssuers: ["did:web:example.com"], // defaults to trust any issuer
assertExpiry: true, // defaults to true
assertNotBefore: true, // defaults to true
checkRevocation: true, // defaults to true
};

const verifier = await init(initOptions);

Verify a credential:

const verifyResult = await verifier.compact.verify({ payload });

if (verifyResult.isErr()) {
// Handle error from verifyResult.error
return;
}

const { verified } = verifyResult.value;

Close the verifier:

console.log(verifier.isOpen()); // true

const closeVerifierResult = await verifier.close();

if (closeVerifierResult.isErr()) {
// Handle error from closeVerifierResult.error
return;
}

console.log(verifier.isOpen()); // false

Destroy the verifier:

await verifier.destroy();

console.log(verifier.isOpen()); // false

Cache

Get the cache expiry date:

const expiry = await verifier.compact.getCacheExpiry();

Refresh the items in the cache:

const refreshCacheResult = await verifier.compact.refreshCache();

if (refreshCacheResult.isErr()) {
/**
* The error contains the cache expiry date
* This date may have changed after partial refresh
*/
console.log(refreshCacheResult.error.expiryDate);
// Handle error from refreshCacheResult.error
return;
}

// New expiry date of the cache
const { expiryDate } = refreshCacheResult.value;

Refresh issuer items in the cache:

const refreshIssuerCacheResult = await verifier.compact.refreshIssuerCache();

if (refreshIssuerCacheResult.isErr()) {
/**
* The error contains the cache expiry date
* This date may have changed after partial refresh
*/
console.log(refreshIssuerCacheResult.error.expiryDate);
// Handle error from refreshIssuerCacheResult.error
return;
}

// New expiry date of the issuers cache
const { expiryDate } = refreshIssuerCacheResult.value;

Refresh revocation list items in the cache:

const refreshRevocationListCacheResult = await verifier.compact.refreshRevocationCache();

if (refreshRevocationListCacheResult.isErr()) {
/**
* The error contains the cache expiry date
* This date may have changed after partial refresh
*/
console.log(refreshRevocationListCacheResult.error.expiryDate);
// Handle error from refreshRevocationListCacheResult.error
return;
}

// New expiry date of the revocation list cache
const { expiryDate } = refreshRevocationListCacheResult.value;

Extensions

The following extensions are not included in the @mattrglobal/verifier-sdk-react-native package by default.

mDocs

In this SDK mDocs are referred to as Mobile Credentials.

To enable mDocs features, install the following peer dependency in your app:

yarn add @mattrglobal/mobile-credential-verifier-react-native

Platform iOS

mDocs presentation utilises Bluetooth connection. Make sure the NSBluetoothAlwaysUsageDescription and NSBluetoothPeripheralUsageDescription descriptions are configured inside Info.plist.

Platform Android

Additional configuration steps are required to bundle the native libraries.

Local Maven Repository

The precompiled MATTR mDocs verifier Android SDK is provided in the published NPM package.

Open the android/build.gradle script and apply the following changes:

 allprojects {
repositories {

google()
+ maven {
+ url = "$rootDir/../node_modules/@mattrglobal/mobile-credential-verifier-react-native/android/frameworks"
+ }
}
}

Enable extension

Include the mDocs verifier extension during initialisation:

import { init } from "@mattrglobal/verifier-sdk-react-native";
import MobileCredentialVerifier from "@mattrglobal/mobile-credential-verifier-react-native";

await init({ extensions: [MobileCredentialVerifier] });

The SDK only verifies credentials that were issued by a trusted issuer. The trusted issuer certificates list can be managed directly with the following functions:

// Add new trusted issuer certificates
await verifier.mobile.addTrustedIssuerCertificates(certificates);

// Get all trusted certificates
const certificates = await verifier.mobile.getTrustedIssuerCertificates();

// Remove one of the trusted issuer certificate
await verifier.mobile.deleteTrustedIssuerCertificate(id);

The mDocs verifier supports requesting a credential from a holder device via Bluetooth. The following example shows how you could start a session and request a credential presentation from a holder device:

Only one presentation session is allowed at a time. You must terminate the existing session before starting a new one.

// start a new presentation session
const createSessionResult = await verifier.mobile.createProximityPresentationSession({
deviceEngagement: "mdoc:owBjMS4wAYIB2BhYS6QBAiABIVgg_t9K0BaXU27ynODS5q8OcvBZ4m1HFEQwl61lhRD2rdciWCA7hKLr_xN6_bdznDePa_yY1tGdHsc8ni_88uVuehRU-QKBgwIBowD1AfQKUMW8DfgLrUclmxp2InJCddk" // proximity presentation device engagement string
onConnected: () => {
// handle onConnect event
},
onSessionTerminated: () => {
// handle onSessionTerminated event
},
});

if (createSessionResult.isErr()) {
const { error } = createSessionResult;
// handle error scenarios
return;
}

// Send session
const sendRequestResult = await verifier.mobile.sendProximityPresentationRequest({
// An optional opt-out flag to bypass additional checks that ensure the credential status is "valid" and not "invalid" or "suspended".
skipStatusCheck: true | false | undefined
mobileCredentialRequests: [{
docType: "org.iso.18013.5.1.mDL",
namespaces: {
"org.iso.18013.5.1": {
family_name: false,
driving_privileges: false,
},
},
}],
});

if (sendRequestResult.isErr()) {
const { error } = sendRequestResult;
// handle error scenarios
return;
}

const response = sendRequestResult.value;

// Terminate current active session
await verifier.mobile.terminateProximityPresentationSession();

Status List Management

The SDK caches status lists on the device and preloads them when verifier.mobile.addTrustedIssuerCertificates is invoked. Subsequent status list updates are lazy-loaded and only fetched when the status list's nextUpdate expires.

You may choose to refresh the cached status lists preemptively or periodically in-order to:

  • Reduce wait times for verifier.mobile.sendProximityPresentationRequest calls by keeping status lists up-to-date.
  • Enable offline verification by refreshing them whenever online to prevent expiration.

More granular management methods are available to help scheduling updates, as shown below:

const statusListsCacheResult = await verifier.mobile.getTrustedIssuerStatusListsCacheInfo();

if(statusListsCacheResult.isErr()) {
const { error } = statusListsCacheResult;
// handle error scenarios
return;
}

const statusListCache = statusListsCacheResult.value;
if(statusListCache.nextUpdate?.getTime() > now.getTime()) {
// Status lists are still up-to-date
return;
}

const statusListInfoResult = await verifier.mobile.updateTrustedIssuerStatusLists();
if(statusListInfoResult.isErr()) {
const { error } = statusListInfoResult;
// handle error scenarios
return;
}

const statusListInfo = statusListInfoResult.value;

if(!statusListInfo.success) {
const { failedStatusLists } = statusListInfo;
// handle error scenarios
return;
}

if(statusListInfo.nextUpdate) {
// Optionally re-schedule the next update or background check
}

Ecosystem

To enable Ecosystem features install the following peer dependency in your app:

yarn add @mattrglobal/ecosystem-sdk-react-native

And then include the Ecosystem SDK during initialisation:

import { init } from "@mattrglobal/verifier-sdk-react-native";
import Ecosystem from "@mattrglobal/ecosystem-sdk-react-native";

await init({ extensions: [Ecosystem], ecosystem: { url } });

On initialisation (see above) the internal storage is synced with the latest policy relevant to the provided ecosystem ID. If storage becomes out of sync, the SDK provides an option to manage the storage manually:

// storage can be synced manually
const syncResult = await verifier.ecosystem.sync({ reset: true });

// storage can be deleted manually
const deleteResult = await verifier.ecosystem.delete();

The main features of the Ecosystem SDK is to provide validation of a given credential and participant, who can be an issuer, a verifier or both. The SDK also checks whether the participant is authorised. This can be invoked with:

// validates the three aspects of the specified issuer
const validateIssuerResult = await Ecosystem.validateIssuer({ profile, identifier, type });

// validates the three aspects of the specified verifier
const validateVerifierResult = await Ecosystem.validateVerifier({ profile, identifier, type });

Error handling

Functions that are expected to have an error path return a Neverthrow Result type that represents either success (Ok) or failure (Err).

Although this pattern is more verbose, it encourages the handling of possible errors and reserves throwing exceptions for truly exceptional situations.

import { open } from "@mattrglobal/verifier-sdk-react-native";

const openVerifierResult = await open();

if (openVerifierResult.isErr()) {
// Handle error from openVerifierResult.error
return;
}

const verifier = openVerifierResult.value;

unwrap

A utility function is provided for convenience if you decide not to handle your errors as results. This function will simply throw an error if the function passed in returns a Result where Result.isErr() is true.

import { unwrap } from "@mattrglobal/verifier-sdk-react-native";

try {
const verifier = unwrap(await open());
} catch (error) {
// Handle thrown error
}

Change Log

5.0.0

Features

mDocs

  • This SDK can now be used in the same application with compatible versions of the mobile-credential-holder-react-native SDK, as detailed in the installation section.

  • mDocs Revocation Support

    • The SDK now supports mDocs revocation.
    • The mobile.sendProximityPresentationRequest method now verifies the status of presented revocable mDocs.
    • MobileCredentialStatusListInfo was added to the return type for both methods under MobileCredentialResponse.credentials[].statusInfo. It is used to:
      • Indicate the credential's status.
      • Detail any error when retrieveing the credential's status fails.
    • The mobile.getTrustedIssuerStatusListsCacheInfo method was added to retrieve cache details of previously retrieved status lists.
    • The mobile.updateTrustedIssuerStatusLists method was added to update status lists when required.
      • Best Practice: It is recommended to call this method before MobileCredentialStatusListInfo.nextUpdate (retrieved from mobile.getTrustedIssuerStatusListsCacheInfo) expires to keep status lists up-to-date. This approachs offers two advantages:
        • It may reduce wait times for subsequent sendProximityPresentationRequest calls, as network requests may be needed to verify a credential's status if the cached status list expires.
        • It can facilitate offline verification.

BREAKING CHANGES

mDocs

  • The mobile.sendProximityPresentationRequest method now checks the status of presented revocable mDocs by default. To opt out of this behavior you must set the new skipStatusCheck parameter to false.

4.0.0

BREAKING CHANGES

  • The react-native-fs peer-dependency has been replaced with react-native-file-access@^3.1.1. You must add this new dependency to your project.
  • When consuming this new version of the SDK, you must update your application dependencies to include @mattrglobal/react-native-cryptography@2.1.1.
  • The SDK now require peer dependencies of react native 0.73.x.

mDocs

  • Realm database has been replaced with a custom storage system. Upgrading to this version will result in all data being lost.

  • The mobile.addTrustedIssuerCertificates method error types were updated as follows:

    • Added MobileCredentialVerifierErrorType.FailedToStoreCertificate when the given certificate is invalid.
    • Removed MobileCredentialVerifierErrorType.InvalidCertificate.
  • The mobile.sendProximityPresentationRequest method error types were updated as follows:

    • Added ProximityPresentationSessionErrorType.UnsupportedCurve.
    • Added ProximityPresentationSessionErrorType.RequestAlreadyInProgress.
    • Removed ProximityPresentationSessionErrorType.MobileCredentialVerificationFailed.
  • The mobile.createProximityPresentationSession method error types were updated as follows:

    • Added ProximityPresentationSessionErrorType.UnsupportedCurve.
  • Instead of throwing an exception, the mobile.sendProximityPresentationRequest method now returns a MobileCredentialResponse with a credentials[x].verificationResult field to provide a more detailed verification status (e.g. invalid credential, etc.).

Features

mDocs

  • iOS Platform

    • mobile.addTrustedIssuerCertificates can now also accept input in the form of an unformatted PEM string.

Notes

  • The react-native-securerandom peer-dependency is no longer required.

3.1.0

Notes

  • The SDK now supports React Native 0.72.14.
  • Replaced the react-native-secure-key-store library with a local secure store implementation. Peer dependency react-native-secure-key-store is no longer required.
  • When consuming this new version of the SDK, you must upgrade your application dependencies to include @mattrglobal/react-native-cryptography@2.0.0.

3.0.0

BREAKING CHANGES

The following verifier initialisation parameters have been renamed to maintain consistency (the functionality is not affected by this change):

  • The assertNotBefore parameter has been renamed to assertValidFrom.
  • The assertExpiry parameter has been renamed to assertValidUntil.

Features

Introduced Mobile Credentials capabilities via extensions.

2.0.0

BREAKING CHANGES

The verifyCredential method had been split and moved into the separate compact and compactSemantic namespaces to simplify methods structure and usage. With this change trusted issuers and revocation lists are cached separately for these namespaces.

  • See methods verifier.compact.verify and verifier.compactSemantic.verify

Features

Introduced Ecosystem capabilities via extensions.

1.0.0

Features

Introduced Compact and Compact Semantic Credentials verification capabilities.

Generated using TypeDoc