MATTR Holder SDK React Native - v8.0.0

MATTR Holder 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

  • Manage local DIDs
  • DIDComm messaging
  • Validate a DID to domain linkage
  • Retrieve credentials over OpenID4VCI
  • Retrieve credentials over OIDC Bridge
  • Verify and present JSON credentials
  • Verify CWT credentials
  • Verify Semantic CWT credentials
  • Hold, verify and present mDocs

In this SDK mDocs are referred to as Mobile credentials, CWT credentials are referred to as Compact credentials and JSON credentials are referred to as Web Credentials.

Supported operating systems

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

Getting started

How to get access to MATTR Pi Holder 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 Get in touch.

Install dependencies

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

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

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

Install the peer dependencies:

yarn add realm@12.1.0 react-native-file-access@^3.1.1 @mattrglobal/rn-bbs-signatures@^1.1.0 react-native-get-random-values@^1.11.0 @mattrglobal/react-native-cryptography@^2.1.1 @mattrglobal/pairing-crypto-rn@^0.4.1

Android only

Make sure the following repository is included under android/build.gradle > allprojects.repositories:

allprojects {
repositories {
...
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
...
}
}

iOS only

Add the pod for bbs-signatures to the podfile in ios/Podfile:

  pod 'bbs-signatures', :git => 'https://github.com/mattrglobal/ffi-bbs-signatures'

Run pod install:

cd ios && pod install

Add arm64 to all profiles under: xcode -> Build Settings -> Excluded Architectures -> Any iOS Simulator SDK, it should show the following changes under xxx.xcodeproj for each of the profiles

"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;

If your app was initially created with react-native@0.61.* or earlier versions, you may need to update your ios/*.xcodeproj configuration. Any reference of the DEAD_CODE_STRIPPING flag must be removed or set to YES, this is required to maintain compatibility for the newer & older versions of react-native.

- DEAD_CODE_STRIPPING = NO;

Usage

Wallet

Initialise a wallet instance

import { initialise } from "@mattrglobal/wallet-sdk-react-native";

const initialiseWalletResult = await initialise();

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

const wallet = initialiseWalletResult.value;

It is possible to maintain multiple isolated wallet instances. This can be achieved by using a different instanceId during initialisation, as long as you close the current wallet instance before initialising a new one with a different instanceId.

import { initialise } from "@mattrglobal/wallet-sdk-react-native";

// to use wallet1
const initialiseWallet1Result = await initialise({ instanceId: "id1" });

if (initialiseWallet1Result.isErr()) {
// Handle error from initialiseWalletResult.error
return;
}
const wallet1 = initialiseWallet1Result.value;

// to use wallet2
await wallet1.close();
const initialiseWallet2Result = await initialise({ instanceId: "id2" });
const wallet2 = initialiseWallet1Result.value;

Destroy the wallet

You must close the wallet instance that is currently initialised before calling destroy, otherwise an exception will be thrown.

import { destroy } from "@mattrglobal/wallet-sdk-react-native";

await destroy({ instanceId });

Retrieving credentials via OpenID4VCI

Discover credential offer details via offer URI

/***
* openid-credential-offer://?credential_offer=encodeURIComponent(JSON.stringify({ credential_issuer, credentials: [{credentialId}], request_parameters? }))
*/
const uri =
"openid-credential-offer://?credential_offer=%7B%22credential_issuer%22%3A%22https%3A%2F%2Fmyissuer.example.com%22%2C%22credentials%22%3A%5B%22707e920a-f342-443b-ae24-6946b7b5033e%22%5D%2C%22request_parameters%22%3A%7B%22login_hint%22%3A%22user%40example.com%22%2C%22prompt%22%3A%22login%22%7D%7D";

const discoveryResult = await wallet.openid.issuance.discover(uri);
if (discoveryResult.isErr()) {
// Handle error from discoveryResult.error
}
const { offer } = discoveryResult.value;

Or construct an offer manually

const offer: OpenidIssuanceCredentialOffer = {
issuer: "https://example.com/",
authorizeEndpoint: "https://example.com/oauth/authorize",
tokenEndpoint: "https://example.com/oauth/token",
credentialEndpoint: "https://example.com/oauth/credential",
credentials: [
{
profile: "web-semantic",
scope: "ldp_vc:UniversityDegreeCredential",
credentialDefinition: {
"@context": ["https://www.w3.org/2018/credentials/v1"],
type: ["VerifiableCredential", "UniversityDegreeCredential"],
},
},
],
};

Configure OAuth client id and redirect uri

const clientId = "myAppClientId";
const redirectUri = "myapp://credentials/callback";

Generate an authorization url and open in a web browser

import { Linking } from "react-native";

const generateAuthorizeUrlResult = await wallet.openid.issuance.generateAuthorizeUrl({ offer, clientId, redirectUri });

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

const { url, codeVerifier } = generateAuthorizeUrlResult.value;
await Linking.openURL(url);

Handle authorization success callback

myapp://credentials/callback?code=...&iss=...

Retrieve token

const retrieveTokenResult = await wallet.openid.issuance.retrieveToken({
offer,
clientId,
redirectUri,
codeVerifier,
code: route.params.code, // code comes authorization success callback above
});

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

const { accessToken } = retrieveTokenResult.value;

Retrieve credentials

const retrieveCredentialsResult = await wallet.openid.issuance.retrieveCredentials({
offer,
accessToken,
clientId,
});

retrieveCredentialsResult.forEach((credentialOfferResult) => {
if ("error" in credentialOfferResult) {
const { offer, error } = credentialOfferResult;

// Handle error from retrieveCredentialsResult.error
} else {
const { offer, result } = credentialOfferResult;
}
});

Retrieving credentials via OIDC Bridge

Discover OIDC credential offer

const discoverResult = await wallet.oidc.discover("openid://discovery?issuer=https://issuer.example.com");

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

const { offer } = discoverResult.value;

Create a local subject DID for the credential

const createDidResult = await wallet.did.createDid();

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

const { did } = createDidResult.value;

Generate an OpenID authorization url to request the credential

import { Linking } from "react-native";

const genUrlResult = await wallet.oidc.generateAuthorizeUrl({ offer, did });

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

const { url, codeVerifier, nonce } = genUrlResult.value;
await Linking.openURL(url);

Retrieve the credential on an authorization success callback

const retrieveResult = (retrieveCredential = await wallet.oidc.retrieveCredential({
offer,
codeVerifier,
nonce,
code: route.params.code, // code comes from part of the callback url
}));

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

const { credential } = retrieveResult.value;

DIDComm message

Resolve a didcomm message from a didcomm URI

const resolveDidCommUriResult = await wallet.did.messaging.resolveDidCommUri(uri);
if (resolveDidCommUriResult.isErr()) {
// Handle error from resolveDidCommUriResult.error
return;
}
const message = resolveDidCommUriResult.value;

Open a didcomm message that is signed or encrypted

import { isPresentationRequestJwm } from "wallet-sdk-react-native";
const openResult = await wallet.did.messaging.openDidCommMessage(message);
if (openResult.isErr()) {
// Handle error from openResult.error
return;
}

JSON Credentials

Verify a JSON credential

const verifyResult = await wallet.credential.webSemantic.verifyCredential({ credential });

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

const { credentialVerified, status } = verifyResult.value;

Parse a presentation request (DIDComm message)

import { isPresentationRequestJwm } from "wallet-sdk-react-native";
const openResult = await wallet.did.messaging.openDidCommMessage(message);

if (openResult.isErr() || !isPresentationRequestJwm(openResult.value)) {
return;
}

const presentationRequest = openResult.value;

Retrieve credentials matching a specific presentation request

const credentialData = [
{ id: "a", credential: credentialA },
{ id: "b", credential: credentialB },
];

const filterResult = await wallet.credential.webSemantic.filterCredentialsByQuery({
credentials: credentialData,
// Note that only the presentation request body should contain single query only, under the same query could contain multiple sub queries.
query: presentationRequest.body.query[0],
});

Create and send a presentation response for a presentation request

const createPresentationResult = await wallet.credential.webSemantic.createPresentation({
challenge: presentationRequest.body.challenge,
domain: presentationRequest.body.domain,
credentials,
holder: did,
});

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

const presentation = createPresentationResult.value;
const sendPresentationResult = await wallet.credential.webSemantic.sendPresentationResponse({
presentationRequest,
presentation,
});

CWT Credentials

Verify a CWT credential

const credentialPayload = "CSC:/1/....";
const verifyResult = await wallet.credential.compact.verifyCredential({ payload: credentialPayload });

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

if (result.value.verified) {
const { payload } = result.value;
} else {
const { reason } = result.value;
}

Semantic CWT Credentials

Verify a Semantic CWT Credential

const credentialPayload = "CSS:/1/....";
const verifyResult = await wallet.credential.compactSemantic.verifyCredential({ payload: credentialPayload });

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

if (result.value.verified) {
const { payload } = result.value;
} else {
const { reason } = result.value;
}

Extensions

The @mattrglobal/wallet-sdk-react-native package does not come with the following extensions by default.

mDocs

In this SDK mDocs are referred to as Mobile Credentials.

To enable mDocs features, an additional peer dependency @mattrglobal/mobile-credential-holder-react-native is needed. Install the following dependency in your app.

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

Platform iOS

mDocs presentation utilise 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 holder Android SDK is provided in the published NPM package.

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

 allprojects {
repositories {

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

Enable extension

Include the mDocs holder extension during initialisation

import { initialise } from "@mattrglobal/wallet-sdk-react-native";
import MobileCredentialHolder from "@mattrglobal/mobile-credential-holder-react-native";

await initialise({ extensions: [MobileCredentialHolder], instanceId });

The same extension is required when destroying a wallet instance

import { destroy } from "@mattrglobal/wallet-sdk-react-native";
import MobileCredentialHolder from "@mattrglobal/mobile-credential-holder-react-native";

await destroy({ extensions: [MobileCredentialHolder], instanceId });

User Authentication

The mDocs holder extension utilise Apple iOS Keychain and Android Key Store to manage cryptographic keys and perform crypto operations securely. By default the policy requires user authentication before providing access to the key store (i.e. biometric or passcode).

When the mDocs holder extension is enabled, the following functions may require user authentication. This would result in an error when no suitable user authentication mechanism is setup on the device, or when authentication fails:

  • initialise: when initialising a wallet instance, user authentication is required to unlock the secure storages. This can be disabled by passing the userAuthRequiredOnInitialise: false option

  • wallet.openid.issuance.retrieveCredentials: when retrieving an mDoc, user authentication is required to generate proof of possession of the credential's binding device key.

  • wallet.credential.mobile.sendPromixityPresentationResponse and OnlinePresentationSession#sendResponse: when creating either in-person or online presentation responses, user authentication is required to sign the response payload.

A grace period was put in place to prevent frequent re-authentication requests when accessing/using multiple cryptographic keys in quick succession (for example when creating an mDoc presentation involving multiple credentials and hence multiple keys).

Retrieving mDocs via OpenID4VCI

With the mobile credential holder extension, the SDK will be able to retrieve mDocs over OpenID4VCI.

mDocs will be verified automatically as part of retrieveCredentials, if the mDocs issued from the remote credential issuer are not verified, retrieveCredentials will return error instead.

import { CredentialProfileSupported } from "@mattrglobal/wallet-sdk-react-native";
const retrieveCredentialsResult = await wallet.openid.issuance.retrieveCredentials({
offer, // offer that contains mDocs
accessToken,
clientId,
});

retrieveCredentialsResult.forEach((credentialOfferResult) => {
if ("error" in credentialOfferResult) {
const { offer, error } = credentialOfferResult;
// Handle error from retrieveCredentialsResult.error
} else {
const { offer, result } = credentialOfferResult;
if (result.profile === CredentialProfileSupported.Mobile) {
const credentialId = result.credentialId;
}
}
});

The SDK manages the storage of any retrieved mDocs and these are accessible via the following functions

getCredentials only retrieves credential metadata, without accessing the full credentials. The credential metadata doesn't include any PII information (i.e. claims' value) or verification result. If you want to get the claim values or the latest verification result of the credential, you should retrieve it from calling getCredential individually.

// Get an mDoc with full details
const getCredentialResult = await wallet.credential.mobile.getCredential(credentialId);

// Get all mDocs (metadata only)
const getCredentialsResult = await wallet.credential.mobile.getCredentials();

// Delete an mDoc
await wallet.credential.mobile.deleteCredential(credentialId);

The SDK only accepts mDocs that can be verified successfully by the trusted issuer certificates. The trusted issuer certificates list can be managed directly with the following functions:

// Add new trusted issuer certificates
const addCertificateResult = await wallet.credential.mobile.addTrustedIssuerCertificates(certificates);

// Get all trusted issuer certificates
const certificates = await wallet.credential.mobile.getTrustedIssuerCertificates();

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

You may also instruct the SDK to automatically download and add certificates into the trusted list while retrieving an mDoc via OpenID4VCI, when they are discoverable via the openid credential issuer metadata:

const retrieveCredentialsResult = await wallet.openid.issuance.retrieveCredentials({
offer, // offer that contains mDocs
accessToken,
clientId,
autoTrustMobileCredentialIaca: true, // enable auto trust
});

Presenting mDocs with In-Person Proximity Presentation

The mDoc holder extension supports proximity presentation, which allows the holder application to present credentials to a verifier device via Bluetooth as defined in ISO 18013-5. The following example shows how you could start and respond to a proximity credential presentation request from a verifier device.

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

When a proximity presentation request is received, you must respond to it before any new request can be received in the same session.

The SDK follows the guidance from ISO/IEC 18013-5:2021 with a session inactivity timeout of 300 seconds. Once a proximity presentation session is created, if there is a period of inactivity that exceeds 300 seconds, the current session will be terminated with onSessionTerminated() callback.

Similar to getCredentials, the matchedCredentials only contains credential metadata. If you want to get the claim values or the latest verification result of the credential, you should retrieve it by calling getCredential individually

// start a new presentation session
const createPresentationSessionResult = await wallet.credential.mobile.createProximityPresentationSession({
onRequestReceived: (data) => {
// request received with error
if ("error" in data) {
const { error } = data;
return;
}

const requests = data.request;
requests.map(({ request, matchedCredentials }) => {
// obtain each request with matching credentials in the mDocs storage
});
},
onConnected: (data: unknown) => {
// presentation session is connected
},
onSessionTerminated: (data: unknown) => {
// presentation session is terminated
},
});

if (createPresentationSessionResult.isErr()) {
// handle error creating presentation session
}

const { deviceEngagement } = createPresentationSessionResult.value;
// Render device engagement string on a QRCode. A verifier app should scan and use it to establish the presentation session with this holder.

// construct and send a presentation response with the selected credentials
await wallet.credential.mobile.sendProximityPresentationResponse({ credentialIds });

// terminate the session
await wallet.credential.mobile.terminateProximityPresentationSession();

Presenting mDocs with Online Presentation

The mDocs holder extension also supports online presentation, which allows the holder application to present credentials to an online verifier web application via OpenID4VP as defined in ISO 18013-7. The following example shows how you could start and respond to an online presentation request from a verifier web application.

Similar to getCredentials, the matchedCredentials only contains credential metadata. If you want to get the claim values or the latest verification result of the credential, you should retrieve it by calling getCredential individually.

// start a new presentation session
const createPresentationSessionResult = await wallet.credential.mobile.createOnlinePresentationSession({
authorisationRequestUri: "..."
});

if (createPresentationSessionResult.isErr()) {
// handle error creating presentation session
}

const session = createPresentationSessionResult.value;
// Render the verifier information stored in `session.verifiedBy`.
// Render the list of matched credentials for each received request stored in `session.matchedCredentials` for user to select.

const { matchedCredentials } = session;

// construct and send a presentation response with the selected credentials
const sendResponseResult = await session.sendResponse({ credentialIds });

// in case of error, could either terminite the session or try to createOnlinePresentationSession again
if (sendResponseResult.isErr()) {
await session.terminateSession();
}

An online presentation request is always signed by the verifier client. By default the SDK will validate the request based on the verifier client domain. You may also instruct the SDK to strictly validate the request against a list of local trusted verifier certificates. This requires the user to set up the list of trusted verfier certificates before creating an online presentation. The list of trusted verifier certificates can be managed directly with the following functions:

// Add new trusted verifier certificates
const addCertificateResult = await wallet.credential.mobile.addTrustedVerifierCertificates(certificates);

// Get all trusted verifier certificates
const certificates = await wallet.credential.mobile.getTrustedVerifierCertificates();

// Remove one of the trusted verifier certificate
await wallet.credential.mobile.deleteTrustedVerifierCertificate(id);

// start a new presentation session with requireTrustedVerifier on
const createPresentationSessionResult = await wallet.credential.mobile.createOnlinePresentationSession({
authorisationRequestUri: "...",
requireTrustedVerifier: true
});

Ecosystem

The Ecosystem SDK provides the capabilities of the ecosystem feature. To enable the feature, an additional peer dependency @mattrglobal/ecosystem-sdk-react-native is needed, which can be installed with:

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

And then include the ecosystem SDK during initialisation:

import { initialise } from "@mattrglobal/wallet-sdk-react-native";
import Ecosystem from "@mattrglobal/ecosystem-sdk-react-native";

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

The same extension is also required to destroy a wallet instance:

import { destroy } from "@mattrglobal/wallet-sdk-react-native";
import Ecosystem from "@mattrglobal/ecosystem-sdk-react-native";

await destroy({ extensions: [Ecosystem] });

On initialisation, previously mentioned, the internal storage is synced with latest policy relevant to the ecosystem ID provided. In case, storage becomes out of sync, the SDK provides managing the storage manually:

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

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

The main features of the SDK is to provide validation of a given credential and participant, who can be an issuer or a verifier, or both, and 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 possibly errors and reserves throwing exceptions for truly exceptional situations.

import { initialise } from "@mattrglobal/wallet-sdk-react-native";

const initialiseWalletResult = await initialise();

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

const wallet = initialiseWalletResult.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/wallet-sdk-react-native";

try {
const wallet = unwrap(await initialise());
} catch (error) {
// Handle thrown error
}

Change Log

8.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 in 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 requires 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 mDocs related data being lost. This includes all trusted issuer certificates and credentials.

  • The credentail.mobile.getCredentials method now returns an array of MobileCredentialMetadata which only contains credentials metadata, excluding Personally Identifiable Information (PII) and latest verification result.

  • The onRequestReceived callback of a Proximity Presentation session now contains matchedCredentials as an array of MobileCredentialMetadata which contains credentials metadata, excluding Personally Identifiable Information (PII) and latest verification result.

  • The initialise method error types were updated as follows:

    • Added UserAuthenticationOnInitChangedError when a different userAuthRequiredOnInitialise option has been specified during re-initialisation of the SDK. This error type is only applicable when the userAuthRequiredOnInitialise option is used.
    • Added UserAuthenticationBiometryLockoutError when biometry authentication has been locked out on user's device.
  • The credential.mobile.createProximityPresentationSession method error types were updated as follows:

    • Added MobileCredentialHolderErrorType.UnsupportedAuthenticationOption (Android only).
  • The wallet.credential.mobile.sendPromixityPresentationResponse method error types were updated as follows:

    • Added ProximityPresentationSessionErrorType.UserAuthenticationBiometryLockout.
    • Added ProximityPresentationSessionErrorType.UserAuthenticationUnrecoverableKey.
  • The credentail.mobile.addCredential method error types were updated as follows:

    • Added MobileCredentialHolderErrorType.UserAuthenticationOnDeviceNotSetup.
    • Added MobileCredentialHolderErrorType.AuthenticationCancelled.
    • Added MobileCredentialHolderErrorType.UserAuthentication.
  • The credentail.mobile.addTrustedIssuerCertificates method error types were updated as follows:

    • Added MobileCredentialHolderErrorType.FailedToStoreCertificate when the given certificate is invalid.
    • Removed MobileCredentialHolderErrorType.InvalidCertificate.
  • The following error types were renamed to properly reflect that a user authetication prompt (biometric or passcode) has been cancelled by either the user or the device OS:

    • For the initialise method:

      • UserAuthenticationCancelledError was renamed to AuthenticationCancelledError.
    • For the wallet.openid.issuance.retrieveCredentials method:

      • MobileCredentialHolderErrorType.UserAuthenticationCancelled was renamed to MobileCredentialHolderErrorType.AuthenticationCancelled.
    • For the wallet.credential.mobile.sendPromixityPresentationResponse method:

      • ProximityPresentationSessionErrorType.UserAuthenticationCancelled was renamed to ProximityPresentationSessionErrorType.AuthenticationCancelled.
    • For the OnlinePresentationSession#sendResponse method:

      • ProximityPresentationSessionErrorType.UserAuthenticationCancelled was renamed to ProximityPresentationSessionErrorType.AuthenticationCancelled.

Features

mDocs

  • Introduced support for mDocs online presentation via OpenID4VP as defined in ISO/IEC 18013-7:2024.

  • The initialise method now supports an optional parameter to control whether user authentication (biometric or passcode) is required when initialising the SDK. By default, when this option is not provided user authentication will be required. The SDK cannot accept further changes to this option with a particular wallet instance.

  • The credential.mobile.getCredential method could return an mDoc with additional verification failure reason types:

    • MobileCredentialVerificationFailureType.DeviceKeyInvalid.
    • MobileCredentialVerificationFailureType.UnsupportedCurve.

Bug Fixes

mDocs

  • Fixed an issue where the credential.mobile.createProximityPresentationSession method was not returning MobileCredentialHolderErrorType.BluetoothPermissionDenied error when the user denies the Bluetooth permission request.

Notes

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

7.0.1

Bug Fixes

  • To mitigate a potential race condition issue, we have improved the process of generating new encryption keys.

Notes

  • When consuming this new version of the SDK, you must upgrade your application dependencies to include @mattrglobal/react-native-cryptography@2.0.0.

7.0.0

BREAKING CHANGES

Web Semantic Credential

  • The SDK now does not allow use of inline or remote contexts by default:
    await initWalletConfig({
...
credential: {
webSemantic: {
remoteContextUrlAllowList: [...], // a list of allowed remote context urls, default: []
remoteContextUrlAllowAny: false // allow any remote context, default: false
inlineContextAllowAny: false, // allow any inline context, default: false
contextValidatorMaxDepth: 10, // max level of nested JsonLD document supported during context validation, default: 10
},
},
})

To use any remote contexts, you will need to manually add them to the remoteContextUrlAllowList array.

Features

Web Semantic Credential

  • The credential.webSemantic.filterCredentialsByQuery method now filters out credentials with invalid contexts instead of returning an error.
  • Return error type has changed from FilterWebSemanticCredentialsByQueryError to PresentationRequestError.
  • The SDK now supports React Native 0.72.14.
  • The react-native-secure-key-store library was replaced with a local secure store implementation, so peer dependency react-native-secure-key-store is no longer required.

Mobile Credential

  • Mobile Credentials now support clock skew tolerance (@mattrglobal/mobile-credential-holder-react-native >= 2.2.4)

6.1.3

Web Semantic Credential

  • Add support to validate the use of inline or remote contexts.
    await initWalletConfig({
...
credential: {
webSemantic: {
remoteContextUrlAllowList: [...], // a list of allowed remote context urls, default: undefined, set this to [] to block any remote context
remoteContextUrlAllowAny: true, // allow any remote context, default: true
inlineContextAllowAny: true, // allow any inline context, default: true
contextValidatorMaxDepth: 10, // max level of nested JsonLD document supported during context validation, default: 10
},
},
})

6.1.2

Bug Fixes

  • Fixed dependency issue on 6.1.1

6.1.1

Bug Fixes

  • Fixed network error detection for the following methods:

    • wallet.credential.webSemantic.createPresentation

Mobile Credential

  • Android Platform
    • Fixed error getting mobile credentials when one of the trusted issuer certificates is expired

6.1.0

Features

Mobile Credential

  • credential.mobile.sendProximityPresentationResponse added an optional parameter terminateSession: boolean which controls whether to terminate the session as a part of sending the response

Bug Fixes

Mobile Credential

  • Android Platform
    • Improved biometric authentication detection for devices with Android 10 (API Level 29) or lower
    • Improved local authentication error handling
    • Refined mobile credential verification result with detailed failure reason to improve the usability
    • Fixed device key JWK encoding with the correct padding
  • iOS Platform
    • Refined mobile credential verification result with detailed failure reason to improve the usability
    • Fixed proximity presentation response encoding issue for requests with no matched claims
    • Fixed Bluetooth connectivity detection for a proximity presentation session

6.0.0

BREAKING CHANGES

  • Rename fields on compact.verifyCredential and compactSemantic.verifyCredential
    • from assertExpiry to assertValidUntil
    • from assertNotBefore to assertValidFrom
  • rename values in VerifyFailureReasonType
    • from Expired to ValidUntil
    • from NotActive to ValidFrom

Features

Add support for web-semantic credentials with an issuanceDate in the future:

  • allow verification of web-semantic credentials with an issuanceDate in the future by adding an inactive status to VerifyWebSemanticCredentialResult to indicate that credential is inactive
  • allow creating presentations of web-semantic credentials with an issuanceDate

Expose NetworkError in case a remote request fails due to a network error or timeout in the following methods:

  • wallet.openid.isssuance.discover
  • wallet.openid.isssuance.retrieveToken

Bug Fixes

  • Refined did.messaging.resolveDidCommUri error results for remote DIDComm URI resolution responses, it could return

    • ResolveDidCommUriErrorType.NetworkError when the DIDComm URI is unresolvable
    • ResolveDidCommUriErrorType.InvalidDidCommUri when the resolution result does not conform to a valid DIDComm message
  • Improved network error detection for the following methods:

    • wallet.credential.webSemantic.createPresentation
    • wallet.did.messaging.openDidCommMessage

Notes

  • Dependency upgrades and vulnerability fixes
  • Removed the unused @mattrglobal/bbs-signatures dependency

5.0.0

BREAKING CHANGES

  • The initialise method could return the following errors:

    • UserAuthenticationUnrecoverableKeyError when user authentication key is unrecoverable, it requires re-initialisation of the SDK. This error type is only applicable on Android platform when @mattrglobal/mobile-credential-holder-react-native is enabled.
    • EcosystemInitialiseError when failed to initialise the @mattrglobal/ecosystem-sdk-react-native extension.
  • Refined error type for the did.messaging.resolveDidCommUri method to the following values:

    • ResolveDidCommUriErrorType.InvalidDidCommUri when provided URI does not resolve into a did comm message
    • ResolveDidCommUriErrorType.NetworkError when unable to resolve the DIDComm URI due to network issue
  • Expose NetworkError in case a remote request fails due to a network error or timeout in the following methods:

    • did.messaging.openDidCommMessage could return NetworkError when unable to resolve a remote DID document
    • credential.webSemantic.createPresentation could return NetworkError when unable to resolve a remote DID document

Features

  • Add Android support for mobile credential. Integration of the @mattrglobal/mobile-credential-holder-react-native extension into wallet sdk is now supported on both iOS and Android platforms. The current functionality includes

    • Retrieving mobile credentials over OpenID4VCI
    • Manage mobile credential store
    • Manage mobile credential trusted issuer certificates
    • Present mobile credentials to a verifier device over bluetooth
  • Cache the remote DID document resolution to prevent unnecessary requests.

  • Add support for ecosystem functionality from @mattrglobal/ecosystem-sdk-react-native extension. The current functionality includes:

    • Synchronize and cache ecosystem policies for the current ecosystem instance
    • Delete all cached policies of the current ecosystem instance
    • Validate that the specified issuer, or verifier, is authorized to issue, or verify, the credential, respectively
    • A new peer dependency is required @mattrglobal/ecosystem-sdk-react-native

Bug Fixes

  • Fix did.messaging.openDidCommMessage to return error result for remote resolution with non 2xx responses

Documentation

Notes

  • Dependency upgrades and vulnerability fixes

4.0.0

BREAKING CHANGES

  • No longer allow having multiple wallet instance with difference walletIds initialised at the same time. Before initialising a wallet instance with a different walletId, the current instance must be closed first.

    import { initialise } from "@mattrglobal/wallet-sdk-react-native";
    // Previously, the following is allowed.
    const initialiseResult1 = await initialise(walletId1);
    if (initialiseResult1.isErr()) {
    return;
    }
    const wallet1 = initialiseResult1.value;

    const initialiseResult2 = await initialise(walletId2);
    if (initialiseResult2.isErr()) {
    return;
    }
    const wallet2 = initialiseResult2.value;

    // Now, the existing wallet must be closed first
    const initialiseResult1 = await initialise(walletId1);
    if (initialiseResult1.isErr()) {
    return;
    }
    const wallet1 = initialiseResult1.value;
    await wallet1.close();

    const initialiseResult2 = await initialise(walletId2);
    if (initialiseResult2.isErr()) {
    return;
    }
    const wallet2 = initialiseResult2.value;
  • Wallet instance must be closed if it is currently initialised before calling destroy, otherwise an exception will be thrown.

  • Remove error type MalformedEncryptionKeyError that is actually unreacble on destroy method

  • Realm now requires >=12.1.0 as peer dependencies to avoid security vulnerability issue in Realm 11.

  • refine error types for wallet.credential.webSemantic.sendPresentationResponse

    • Removed SendWebSemanticPresentationResponseErrorType.FailedToSendPresentationResponse error type
    • Return SendWebSemanticPresentationResponseErrorType.VerificationFailed error when presentation response endpoint returns 400 Bad Request, which indicates an failure of verifying the presentation response
    • Return SendWebSemanticPresentationResponseErrorType.VerifierUnavailable error when presentation response endpoint, returns 504 Gateway Timeout, which indicates the verifier is unavailable. The details of the error will contain the verified for the result of the presentation verification.

Features

  • Add support for mobile credential (iOS Only). This allows user to integrate the mobile credential functionality from @mattrglobal/mobile-credential-holder-react-native into the wallet sdk. The current functionality includes

    • Retrieving mobile credentials over OpenID4VCI
    • Manage mobile credential store
    • Manage mobile credential trusted issuer certificates
    • Present mobile credentials to a verifier device over bluetooth
  • wallet.did.messaging.openDidCommMessage now checks JWM message expiries_time when available and return error if the message is expired.

  • wallet.credential.webSemantic.sendPresentationResponse now includes expires_time in the message

Notes

  • Dependencies upgrade and vulnerability fixes

3.0.0

BREAKING CHANGES

  • Support partial failure in wallet.webSemantic.retrieveCredentials method:

    • retrieveCredentials method no longer return error result if it fails to retrieve one of the credentials, instead it returns a union of credentials and errors.

      const retrieveCredentialsResult = await wallet.openid.issuance.retrieveCredentials({
      offer,
      accessToken,
      clientId,
      });

      /**
      * Example `retrieveCredentialsResult`
      * [
      * {
      * offer,
      * credential, // Successfully retrieved verifiable credential
      * },
      * {
      * offer,
      * error: { type, message, cause }, // Failure
      * }
      * ]
      */
  • Expose NetworkError in case a remote request fails due to a network error or timeout in the following methods:

    • wallet.credential.webSemantic.verifyCredential could return type VerifyWebSemanticCredentialErrorType.NetworkError
    • wallet.credential.webSemantic.deriveCredential could return type DeriveWebSemanticCredentialErrorType.NetworkError
    • wallet.credential.webSemantic.expandCredential could return type ExpandWebSemanticCredentialErrorType.NetworkError
    • wallet.credential.webSemantic.sendPresentationResponse could return type SendWebSemanticPresentationResponseErrorType.NetworkError
    • wallet.credential.webSemantic.filterCredentialsByQuery could return type PresentationRequestErrorType.NetworkError
    • wallet.openid.issuance.retrieveCredentials could return type RetrieveCredentialsErrorType.NetworkError in the new partial error format (see item above)
  • Consolidate create and open into initialise method

    // Previously
    import { create, open } from "@mattrglobal/wallet-sdk-react-native";
    const createWalletResult = await create();
    if (createWalletResult.isErr()) {
    return; // Handle error from createWalletResult.error
    }
    const openWalletResult = await open();
    if (openWalletResult.isErr()) {
    return; // Handle error from openWalletResult.error
    }
    const wallet = openWalletResult.value;
    ...

    // Now
    import { initialise } from "@mattrglobal/wallet-sdk-react-native";
    const initialiseResult = await initialise();
    if (initialiseResult.isErr()) {
    return; // Handle error from initialiseResult.error
    }
    const wallet = initialiseResult.value;
    ...

Bug Fixes

  • Fix webSemantic.verifyCredentials results
    • Do not assume isRevoked to be true if revocation status check failed
    • Do not assume expired to be false if credential signature verification failed

Notes

  • Add support for React Native 0.71

    • Require realm>=11.10.2

2.1.2

  • Add support for BbsSignature2022 verifiable credentials
  • A new peer dependency is required @mattrglobal/pairing-crypto-rn

2.1.1

  • Update change log
  • Address cve in semver dependency

2.1.0

Features

  • Add support to obtain compact and compact semantic credentials over OpenID4VCI
  • Add support to verify compact and compact semantic credentials

Bug Fixes

  • iOS: fix an issue that the keychain got reset after the wallet instance is created.

Notes

  • A new peer dependency is required @mattrglobal/react-native-cryptography

2.0.0

BREAKING CHANGES

  • Wallet SDK Interface:

    • Rename wallet.did.create to wallet.did.createDid
    • Rename wallet.did.delete to wallet.did.deleteDid
    • Rename wallet.did.list to wallet.did.listDids
    • Rename wallet.did.resolve to wallet.did.resolveDid
    • Rename wallet.wellKnownDidConfiguration to wallet.did.wellKnownDidConfiguration
    • Rename wallet.messaging to wallet.did.messaging
    • Rename wallet.credential.isSelectivelyDisclosable to wallet.credential.webSemantic.isCredentialSelectivelyDisclosable
    • Rename wallet.credential.derive to wallet.credential.webSemantic.deriveCredential
    • Rename wallet.credential.verify to wallet.credential.webSemantic.verifyCredential
    • Rename wallet.credential.expand to wallet.credential.webSemantic.expandCredential
    • Rename wallet.presentation.create to wallet.credential.webSemantic.createPresentation
    • Rename wallet.presentation.filterCredentialsByQuery to wallet.credential.webSemantic.filterCredentialsByQuery
    • Rename wallet.presentation.sendPresentationResponse to wallet.credential.webSemantic.sendPresentationResponse
  • Manual Credential Offer:

    • Replace format with profile
const offer: OpenidIssuanceCredentialOffer = {
...,
credentials: [
{
scope: "ldp_vc:UniversityDegreeCredential",
profile: "web-semantic",
credentialDefinition: {
"@context": ["https://www.w3.org/2018/credentials/v1"],
type: ["VerifiableCredential", "UniversityDegreeCredential"],
},
}
],
};
  • Retrieve Credentials:
    • Update return type of wallet.openid.issuance.retrieveCredentials
      • Replace format with profile
{
credentials: {
credential,
profile,
did,
}[];
}

Features

  • Add new top-level method qrcode

Bug Fixes

  • Replace big-integer with bignumber.js for the BigInt polyfill

1.7.1

Notes

  • Internal package maintenance
  • Update iOS installation docs

1.7.0

Features

  • Add support for resolving DIDCommUri

1.6.0

Features

  • Expose document loader timeout value (httpRequestTimeoutMs) under InitOptions and set the default value to 5 seconds.

1.5.0

Features

  • Add support for dynamic discovery (discover credential offer details via offer URI)
/**
* openid-credential-offer://?credential_offer=encodeURIComponent(JSON.stringify({ credential_issuer, credentials: [{credentialId}], request_parameters? }))
*/
const uri =
"openid-credential-offer://?credential_offer=%7B%22credential_issuer%22%3A%22https%3A%2F%2Fmyissuer.example.com%22%2C%22credentials%22%3A%5B%22707e920a-f342-443b-ae24-6946b7b5033e%22%5D%2C%22request_parameters%22%3A%7B%22login_hint%22%3A%22ken.huang%40mattr.global%22%2C%22prompt%22%3A%22login%22%7D%7D";

const offer = unwrap(await wallet.openid.issuance.discover(uri));

Export types:

  • FilterCredentialsByQueryError
  • FilterCredentialsByQueryResponse
  • PresentationRequestError

Update OpenId issuance offer types (WebSemantic)

const offer: OpenidIssuanceCredentialOffer = {
issuer: "https://example.com/",
authorizeEndpoint: "https://example.com/oauth/authorize",
tokenEndpoint: "https://example.com/oauth/token",
credentialEndpoint: "https://example.com/oauth/credential",
credentials: [
{
format: "ldp_vc",
scope: "UniversityDegreeCredential",
credentialDefinition: {
"@context": ["https://www.w3.org/2018/credentials/v1"],
type: ["VerifiableCredential", "UniversityDegreeCredential"],
},
},
],
};

Bug fixes

  • Updated retrieveCredentials to support deprecated options

1.4.1

Bug Fixes

  • Fix React Native android linking

1.4.0

Features

  • Expose some internal types and functions
  • Export types:
    • SecureKeyValueStoreErrorType
    • assertUnreachable

1.3.0

Features

  • Add support for React Native 0.70.0
  • Add support for Hermes engine
  • Migrate to use react-native-secure-key-store 2.0.10

1.2.1

Notes

  • Internal package maintenance

1.2.0

Features

  • Expose type validation functions:
    • isType
    • assertType
    • OpenidIssuanceCredentialOfferValidator
    • AuthorizeRequestParametersValidator
    • CredentialOfferedValidator
    • OpenidIssuanceGenerateAuthorizeUrlOptionsValidator
    • OpenidIssuanceRetrieveCredentialsOptionsValidator

1.1.1

Notes

  • Internal package maintenance

1.1.0

Features

  • Add support for obtaining multiple credentials over OpenID4VCI
  • Add support for React Native 0.68.5

1.0.5

Notes

  • Internal package maintenance

1.0.4

Notes

  • Internal package maintenance

1.0.3

Notes

  • Internal package maintenance

1.0.2

Notes

  • Internal package maintenance

1.0.1

Bug Fixes

  • Add missing polyfil and fix build error

Notes

  • Upgrade @mattrglobal/rn-bbs-signatures version

1.0.0

Features

  • Initialise a wallet
  • Manage local DIDs
  • Verify issuer DIDs to domain linkage
  • Obtain credentials over OIDC Bridge from the issuer
  • Verify credentials
  • Handle presentation request and present credentials to verifier
  • Create and open DID Comm messages

Generated using TypeDoc