Receiving Mobile Credentials in Wallet SDK using OpenID Credential Provisioning
Initialise a wallet instance
@mattrglobal/wallet-sdk-react-native
does not come in mobile credential support by default. To enable the mobile credential feature, an additional peer dependency @mattrglobal/mobile-credential-holder-react-native
is needed. Install the following dependency in your app.
NOTE: mobile credential presentation utilise Bluetooth connection. For iOS make sure the
NSBluetoothAlwaysUsageDescription
andNSBluetoothPeripheralUsageDescription
description are configured insideInfo.plist
.
1yarn add @mattrglobal/mobile-credential-holder-react-native
Include the mobile credential holder extension during initialisation
1import { initialise } from "@mattrglobal/wallet-sdk-react-native";
2import MobileCredentialHolder from "@mattrglobal/mobile-credential-holder-react-native";
3
4await initialise({ extensions: [MobileCredentialHolder], walletId });
Start an OpenID Credential Provisioning flow
Discover OpenID credential offer
1const uri =
2 "openid-credential-offer://?credential_offer=%7B%22credential_issuer%22
3 %3A%22https%3A%2F%2Fmyissuer.example.com%22%2C%22credentials%22%3A%5B%
4 22707e920a-f342-443b-ae24-6946b7b5033e%22%5D%2C%22request_parameters%22
5 %3A%7B%22login_hint%22%3A%22test.user%40example.com%22%2C%22prompt%22%
6 3A%22login%22%7D%7D";
7
8const discoveryResult = await wallet.openid.issuance.discover(uri);
9if (discoveryResult.isErr()) {
10 // Handle error from discoveryResult.error
11}
12const { offer } = discoveryResult.value;
or Construct the offer manually
1const offer: OpenidIssuanceCredentialOffer = {
2 issuer: "https://example.com/",
3 authorizeEndpoint: "https://example.com/oauth/authorize",
4 tokenEndpoint: "https://example.com/oauth/token",
5 credentialEndpoint: "https://example.com/oauth/credential",
6 credentials: [
7 {
8 profile: "mobile",
9 scope: "mso_mdoc:com.example.employeecredential.1",
10 docType: "com.example.employeecredential.1"
11 }
12 ]
13}
Generate an OAuth authorization url to request access token to retrieve the credentials
1import { Linking } from "react-native";
2
3const generateAuthorizeUrlResult = await wallet.openid.issuance.generateAuthorizeUrl({ offer, clientId, redirectUri });
4
5if (generateAuthorizeUrlResult.isErr()) {
6 // Handle error from generateAuthorizeUrlResult.error
7 return;
8}
9
10const { url, codeVerifier } = generateAuthorizeUrlResult.value;
11await Linking.openURL(url);
Retrieve the token
1const retrieveTokenResult = await wallet.openid.issuance.retrieveToken({
2 offer,
3 clientId,
4 redirectUri,
5 codeVerifier,
6 code: route.params.code, // code comes authorization success callback above
7});
8
9if (retrieveTokenResult.isErr()) {
10 // Handle error from retrieveTokenResult.error
11 return;
12}
13
14const { accessToken } = retrieveTokenResult.value;
Retrieve credentials
1import { CredentialProfileSupported } from "@mattrglobal/wallet-sdk-react-native";
2const retrieveCredentialsResult = await wallet.openid.issuance.retrieveCredentials({
3 offer, // offer that contains mobile credentials
4 accessToken,
5 clientId,
6});
7
8retrieveCredentialsResult.forEach((credentialOfferResult) => {
9 if ("error" in credentialOfferResult) {
10 const { offer, error } = credentialOfferResult;
11 // Handle error from retrieveCredentialsResult.error
12 } else {
13 const { offer, result } = credentialOfferResult;
14 if (result.profile === CredentialProfileSupported.Mobile) {
15 const credentialId = result.credentialId;
16 }
17 }
18});
Manage Storage of Mobile Credentials
The SDK manages the storage of any retrieved mobile credential. They will be accessible via the following mobile credential functions.
1// Get a mobile credential
2const getCredentialResult = await wallet.credential.mobile.getCredential(credentialId);
3
4// Get all mobile credentials
5const getCredentialsResult = await wallet.credential.mobile.getCredentials();
6
7// Delete a mobile credential
8await wallet.credential.mobile.deleteCredential(credentialId);
Manage Trusted Issuer Certificates
The SDK only accept a mobile credential that can be verified successfully by the trusted issuer certificates. The trusted issuer certificates list can be managed directly with the following functions
1// Add new trusted issuer certificates
2await wallet.credential.mobile.addTrustedIssuerCertificates(certificates);
3
4// Get all trusted certificates
5const certificates = await wallet.credential.mobile.getTrustedIssuerCertificates();
6
7// Rmove one of the trusted issuer certificate
8await wallet.credential.mobile.deleteTrustedIssuerCertificate(id);
Enable Auto Trust for Issuer Certificates
You may also instruct the SDK to automatically download and add certificates if it's discoverable via the openid credential issuer metadata into the trusted list while retrieving a mobile credential via OpenID4VCI.
1const retrieveCredentialsResult = await wallet.openid.issuance.retrieveCredentials({
2 offer, // offer that contains mobile credentials
3 accessToken,
4 clientId,
5 autoTrustMobileCredentialIaca: true, // enable auto trust
6});
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
}
Find the comprehensive SDK interfaces for these examples and others in the documentation https://github.com/mattrglobal/docs-wallet-sdk.
Get in touch if you wish to find out more about using the Wallet SDK in production.