Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* Import the required functions and types from the MATTR Mobile Credential Verifier SDK.
* These are used throughout the app to:
* - `initialize`: Initialize the SDK so the app can use its functions and classes.
* - `initialize`: Initialize the SDK, registering this app instance with your MATTR VII tenant.
* - `createProximityPresentationSession`: Establish a BLE session with a holder's wallet after scanning their QR code.
* - `sendProximityPresentationRequest`: Send a presentation request to the wallet and receive a verified response.
* - `terminateProximityPresentationSession`: Clean up the session after verification is complete.
Expand Down Expand Up @@ -33,6 +33,7 @@ import {
// - QRScannerModal: Scan a QR code presented by a holder wallet (Tutorial: "Verify mDocs - Step 1")
// - VerificationResultsModal: Display verification results (Tutorial: "Verify mDocs - Step 2")
import { MONTCLIFF_DMV_IACA } from "./certificates";
import { Constants } from "./Constants";
import { QRScannerModal } from "./QRScannerModal";
import { VerificationResultsModal } from "./VerificationResultsModal";
import { styles } from "./styles";
Expand Down Expand Up @@ -73,7 +74,10 @@ export default function App() {
*
* This runs once on app launch and performs two actions:
* 1. Calls `initialize()` to set up the MobileCredentialVerifier SDK so the app
* can use its functions and classes for proximity verification.
* can use its functions and classes for proximity verification. From v10.0.0
* `platformConfiguration` is required: it registers this app instance with your
* MATTR VII tenant (the SDK Backend) and obtains the SDK license. Network access
* is required when registration or license renewal is performed.
* 2. On first launch (no certificates stored yet), registers the sample Montcliff
* DMV IACA certificate so the app is ready to verify the tutorial mDoc out of
* the box. Every mDoc is signed by a chain of trust, so the SDK needs at least
Expand All @@ -83,8 +87,17 @@ export default function App() {
const initializeSDK = async () => {
try {
setLoadingMessage("Initializing SDK...");
const result = await initialize();
const result = await initialize({
platformConfiguration: {
tenantHost: Constants.TENANT_HOST,
applicationId: Constants.APPLICATION_ID,
},
});
if (result.isErr()) {
// `FailedToRegister` means this app instance could not be registered with the
// tenant, and `InvalidLicense` means the SDK license is missing or expired. Both
// require network access and a verifier application whose bundle ID or package
// fingerprint matches this app.
console.error("Failed to initialize SDK:", result.error);
Alert.alert("Error", "Failed to initialize the verifier SDK");
return;
Expand All @@ -93,9 +106,28 @@ export default function App() {

// Setup certificates - Step 1: Register the trusted IACA certificate on first launch.
setLoadingMessage("Loading certificates...");
const certificates = await getTrustedIssuerCertificates();
if (certificates.length === 0) {
await addTrustedIssuerCertificates([MONTCLIFF_DMV_IACA]);
const certificatesResult = await getTrustedIssuerCertificates();
if (certificatesResult.isErr()) {
console.error(
"Failed to read trusted issuer certificates:",
certificatesResult.error,
);
Alert.alert("Error", "Failed to load the trusted issuer certificates");
return;
}

if (certificatesResult.value.length === 0) {
const addResult = await addTrustedIssuerCertificates([
MONTCLIFF_DMV_IACA,
]);
if (addResult.isErr()) {
console.error(
"Failed to add trusted issuer certificate:",
addResult.error,
);
Alert.alert("Error", "Failed to add the trusted issuer certificate");
return;
}
}
} catch (error) {
console.error("Failed to initialize SDK:", error);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Platform } from "react-native";

/**
* Initialize SDK - Step 1.3: Configure the SDK Backend
*
* From SDK v10.0.0 the Verifier SDK is tethered to a MATTR VII tenant. On first initialization it
* registers this app instance with the tenant and obtains the license the SDK needs to operate, so a
* tenant and a verifier application are required even for in-person (proximity) verification.
*
* Replace these placeholders with your own values before running the app:
* - `TENANT_HOST`: the URL of your MATTR VII tenant, available in the MATTR Portal under
* Platform Management > Tenant.
* - `IOS_APPLICATION_ID` / `ANDROID_APPLICATION_ID`: the `id` returned when you created the verifier
* application configuration in the MATTR Portal under Credential Verification > Applications.
* iOS and Android each use their own verifier application, because the application is identified by
* the bundle ID and team ID (iOS) or the package fingerprint (Android) declared in `app.config.ts`.
* Configure one application ID per platform.
*/
const IOS_APPLICATION_ID = "your-ios-application-id";
const ANDROID_APPLICATION_ID = "your-android-application-id";

export const Constants = {
TENANT_HOST: "https://your-tenant.vii.mattr.global",
// Resolves to the verifier application ID for the current platform.
APPLICATION_ID:
Platform.OS === "ios" ? IOS_APPLICATION_ID : ANDROID_APPLICATION_ID,
};
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export function VerificationResultsModal({ visible, onClose, verificationResults
</View>

<ScrollView style={styles.content}>
{verificationResults.credentials && verificationResults.credentials.length > 0 ? (
{verificationResults.credentials.length > 0 ? (
<View>
{/* Verify mDocs - Step 4: Display overall verification status.
Shows whether the first credential in the response passed verification.
Expand All @@ -77,12 +77,12 @@ export function VerificationResultsModal({ visible, onClose, verificationResults
<View style={[styles.center, styles.marginBottom]}>
<Text
style={
verificationResults.credentials[0].verificationResult?.verified
verificationResults.credentials[0].verificationResult.verified
? styles.verificationSuccess
: styles.verificationFailed
}
>
{verificationResults.credentials[0].verificationResult?.verified
{verificationResults.credentials[0].verificationResult.verified
? "✓ Verified"
: "✗ Verification Failed"}
</Text>
Expand Down Expand Up @@ -116,7 +116,7 @@ export function VerificationResultsModal({ visible, onClose, verificationResults
{/* Verify mDocs - Step 4: Display verification failure reason.
If the mDoc did not pass verification (e.g. untrusted issuer,
expired certificate, invalid signature), show the failure type and message. */}
{!credential.verificationResult?.verified && credential.verificationResult?.reason && (
{!credential.verificationResult.verified && (
<View style={styles.card}>
<Text style={styles.listItemTitle}>Verification Failed:</Text>
<Text>Type: {credential.verificationResult.reason.type}</Text>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"web": "expo start --web"
},
"dependencies": {
"@mattrglobal/mobile-credential-verifier-react-native": "^9.0.1",
"@mattrglobal/mobile-credential-verifier-react-native": "^10.0.0",
"expo": "^55",
"expo-build-properties": "~55.0.13",
"expo-camera": "~55.0.15",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"web": "expo start --web"
},
"dependencies": {
"@mattrglobal/mobile-credential-verifier-react-native": "^9.0.1",
"@mattrglobal/mobile-credential-verifier-react-native": "^10.0.0",
"expo": "^55",
"expo-build-properties": "~55.0.13",
"expo-camera": "~55.0.15",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,25 @@ export default function App() {
/**
* Step 2: Initialize the SDK
*
* Runs once on app launch. Unlike the in-person (proximity) flow, the remote flow requires a
* `tenantHost`: the SDK starts presentation sessions with this MATTR VII tenant, which performs the
* verification server-side and returns the results.
* Runs once on app launch. `platformConfiguration` is required from SDK v10.0.0: it registers this
* app instance with your MATTR VII tenant (the SDK Backend) and obtains the license the SDK needs to
* operate. The same tenant starts the presentation sessions, performs the verification server-side
* and returns the results.
*/
useEffect(() => {
const initializeSDK = async () => {
try {
setLoadingMessage("Initializing SDK...");
const result = await initialize({
platformConfiguration: { tenantHost: Constants.TENANT_HOST },
platformConfiguration: {
tenantHost: Constants.TENANT_HOST,
applicationId: Constants.APPLICATION_ID,
},
});
if (result.isErr()) {
// `FailedToRegister` means this app instance could not be registered with the tenant, and
// `InvalidLicense` means the SDK license is missing or expired. Both require network access
// and a verifier application whose bundle ID or package fingerprint matches this app.
console.error("Failed to initialize SDK:", result.error);
Alert.alert("Error", "Failed to initialize the verifier SDK");
return;
Expand Down Expand Up @@ -130,7 +137,6 @@ export default function App() {
// `challenge` must be a unique, unpredictable value for every request to mitigate replay attacks.
const result = await requestMobileCredentials({
request: [mobileCredentialRequest],
applicationId: Constants.APPLICATION_ID,
challenge: Crypto.randomUUID(),
});

Expand All @@ -139,12 +145,14 @@ export default function App() {
}

const session = result.value;
// A session-level failure (aborted, wallet unavailable, verification/response error) is
// signaled by `error` being present on the result. There is no `isSuccess` flag.
if (session.error) {
// `OnlinePresentationSessionResult` is discriminated on `isSuccess`. On a failure result
// (aborted, wallet unavailable, verification or response error) `error` is always present.
if (!session.isSuccess) {
throw new Error(`Verification session failed: ${session.error.message}`);
}

// `mobileCredentialResponse` is absent when the verifier application is configured to deliver
// results over the back channel only, so the credentials never reach this app.
const response = session.mobileCredentialResponse;
if (!response) {
throw new Error("No verification results were returned by the tenant.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,18 @@ export function VerificationResultsModal({ visible, onClose, verificationResults
</View>

<ScrollView style={styles.content}>
{verificationResults.credentials && verificationResults.credentials.length > 0 ? (
{verificationResults.credentials.length > 0 ? (
<View>
{/* Overall verification status for the first credential, as determined by the tenant. */}
<View style={[styles.center, styles.marginBottom]}>
<Text
style={
verificationResults.credentials[0].verificationResult?.verified
verificationResults.credentials[0].verificationResult.verified
? styles.verificationSuccess
: styles.verificationFailed
}
>
{verificationResults.credentials[0].verificationResult?.verified
{verificationResults.credentials[0].verificationResult.verified
? "✓ Verified"
: "✗ Verification Failed"}
</Text>
Expand Down Expand Up @@ -107,7 +107,7 @@ export function VerificationResultsModal({ visible, onClose, verificationResults

{/* Verification failure reason. If the mDoc did not pass verification (e.g. untrusted
issuer, expired certificate, invalid signature), show the failure type and message. */}
{!credential.verificationResult?.verified && credential.verificationResult?.reason && (
{!credential.verificationResult.verified && (
<View style={styles.card}>
<Text style={styles.listItemTitle}>Verification Failed:</Text>
<Text>Type: {credential.verificationResult.reason.type}</Text>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"postinstall": "patch-package"
},
"dependencies": {
"@mattrglobal/mobile-credential-verifier-react-native": "^9.0.1",
"@mattrglobal/mobile-credential-verifier-react-native": "^10.0.0",
"expo": "^55",
"expo-build-properties": "~55.0.13",
"expo-crypto": "~55.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"postinstall": "patch-package"
},
"dependencies": {
"@mattrglobal/mobile-credential-verifier-react-native": "^9.0.1",
"@mattrglobal/mobile-credential-verifier-react-native": "^10.0.0",
"expo": "^55",
"expo-build-properties": "~55.0.13",
"expo-crypto": "~55.0.0",
Expand Down
Loading