light-mode-image
Learn

Changelog

Release notes for the @mattrglobal/mobile-credential-holder-react-native package.

10.0.0

Refer to the migration guide for details on how to update your implementation to this major version.

Breaking Changes

Several functions now return a Result

Seven functions that previously resolved a plain value now return a neverthrow Result, so their expected error cases can be handled without a try/catch. Callers must handle the Result instead of using the resolved value directly.

These functions can still throw, so a try/catch is still required alongside handling the Result. Refer to each function's @throws annotation for the errors it can throw, and to RuntimeException may be thrown by any function.

FunctionPreviouslyNow
deleteCredentialPromise<void>Promise<Result<void, DeleteCredentialError>>
destroyPromise<void>Promise<Result<void, DestroyError>>
deleteTrustedVerifierCertificatePromise<void>Promise<Result<void, DeleteTrustedVerifierCertificateError>>
getCredentialsPromise<MobileCredentialMetadata[]>Promise<Result<MobileCredentialMetadata[], GetCredentialsError>>
getTrustedIssuerCertificatesPromise<TrustedIssuerCertificate[]>Promise<Result<TrustedIssuerCertificate[], GetTrustedIssuerCertificatesError>>
getTrustedVerifierCertificatesPromise<TrustedVerifierCertificate[]>Promise<Result<TrustedVerifierCertificate[], GetTrustedVerifierCertificatesError>>
getCurrentProximityPresentationSessionPromise<ProximityPresentationSession | undefined>Promise<Result<ProximityPresentationSession | undefined, GetCurrentProximityPresentationSessionError>>

The matching error types are now exported from the package:

  • DeleteCredentialError
  • DestroyError
  • DeleteTrustedVerifierCertificateError
  • GetCredentialsError
  • GetTrustedIssuerCertificatesError
  • GetTrustedVerifierCertificatesError
  • GetCurrentProximityPresentationSessionError

Before:

const credentials = await Holder.getCredentials();

After:

try {
  const getCredentialsResult = await Holder.getCredentials();

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

  const credentials = getCredentialsResult.value;
} catch (error) {
  // Handle unexpected thrown errors
}

Credential retrieval results are now discriminated unions

The RetrieveCredentialsResponse array items are now isSuccess-discriminated unions instead of a single object with optional fields. Each item is either a RetrieveCredentialSuccess or RetrieveCredentialFailure, and TypeScript will enforce which fields are available after narrowing.

Before:

for (const item of result) {
  if (item.credentialId) {
    console.log(item.credentialId);
  } else {
    console.log(item.error?.message);
  }
}

After:

for (const item of result) {
  if (item.isSuccess) {
    // item is RetrieveCredentialSuccess — credentialId is guaranteed
    console.log(item.credentialId);
  } else {
    // item is RetrieveCredentialFailure — error is guaranteed
    console.log(item.error.message);
  }
}
  • RetrieveCredentialSuccess has isSuccess: true, docType, and credentialId.
  • RetrieveCredentialFailure has isSuccess: false, docType, and error.
  • The error field is no longer optional - it is always present on failure items and never present on success items.
  • The credentialId field is no longer optional - it is always present on success items and never present on failure items.

doctype renamed to docType

The doctype field has been renamed to docType (camelCase) to align naming across iOS and Android platforms. This affects credential retrieval result items and OfferedCredential (returned by discoverCredentialOffer). Update all references from .doctype to .docType.

MobileCredentialAuthenticationOption renamed to DeviceAuthenticationOption

The MobileCredentialAuthenticationOption enum has been renamed to DeviceAuthenticationOption, and the mobileCredentialAuthenticationOption field of CreateProximityPresentationSessionOptions has been renamed to deviceAuthenticationOption. This aligns naming with the native holder SDKs, which made the same rename in iOS 6.0.0 and Android 7.0.0. The Signature and Mac values are unchanged.

Neither previous name is exported any more, so update all imports, type references, and the option passed to createProximityPresentationSession.

Before:

import { MobileCredentialAuthenticationOption } from "@mattrglobal/mobile-credential-holder-react-native";

const result = await Holder.createProximityPresentationSession({
  onRequestReceived,
  mobileCredentialAuthenticationOption: MobileCredentialAuthenticationOption.Mac,
});

After:

import { DeviceAuthenticationOption } from "@mattrglobal/mobile-credential-holder-react-native";

const result = await Holder.createProximityPresentationSession({
  onRequestReceived,
  deviceAuthenticationOption: DeviceAuthenticationOption.Mac,
});

On Android, passing the old mobileCredentialAuthenticationOption key after upgrading fails with an InvalidParams error rather than being ignored, as described in Android now rejects unknown argument keys. On iOS the key is ignored and the default authentication option is used.

DeviceKeyAuthenticationType removed in favour of UserAuthenticationType

The DeviceKeyAuthenticationType enum export has been removed.

  • Use UserAuthenticationType instead. It now carries the same values: None, UserPresence, BiometryAny, BiometryCurrentSet, and DeviceCredential.
  • Update all references, including the type field of DeviceKeyAuthenticationPolicy passed to generateDeviceKey, retrieveCredentials, and retrieveCredentialsUsingAuthorizationSession.

Before:

const result = await Holder.generateDeviceKey({
  issuer,
  audience,
  authenticationPolicy: { type: DeviceKeyAuthenticationType.BiometryCurrentSet },
});

After:

const result = await Holder.generateDeviceKey({
  issuer,
  audience,
  authenticationPolicy: { type: UserAuthenticationType.BiometryCurrentSet },
});

UserAuthenticationType values have changed

UserAuthenticationType is used for the userAuthenticationType field of userAuthenticationConfiguration passed to initialize.

  • It previously carried only BiometricOnly and BiometricOrPasscode.
  • It now carries None, UserPresence, BiometryAny, BiometryCurrentSet, and DeviceCredential, matching the values used for device key authentication policies.
  • BiometricOnly is replaced by BiometryCurrentSet.
  • BiometricOrPasscode is replaced by UserPresence.
  • The default for userAuthenticationType is now UserPresence, previously BiometricOrPasscode.
  • initialize may now return UserAuthenticationNotSupported on Android when BiometryCurrentSet is combined with a userAuthenticationBehavior of OnInitialize.

Before:

await Holder.initialize({
  userAuthenticationConfiguration: {
    userAuthenticationBehavior: UserAuthenticationBehavior.OnDeviceKeyAccess,
    userAuthenticationType: UserAuthenticationType.BiometricOrPasscode,
  },
});

After:

await Holder.initialize({
  userAuthenticationConfiguration: {
    userAuthenticationBehavior: UserAuthenticationBehavior.OnDeviceKeyAccess,
    userAuthenticationType: UserAuthenticationType.UserPresence,
  },
});

Removed deprecated authentication types

The DeprecatedDeviceKeyAuthenticationType enum (and its BiometricOnly and BiometricOrPasscode values) has been removed. A device key that was previously associated with a deprecated type is now reported as its modern equivalent:

  • BiometricOnlyBiometryCurrentSet
  • BiometricOrPasscodeUserPresence

Update any code that references DeprecatedDeviceKeyAuthenticationType to use the corresponding UserAuthenticationType value.

VerificationResult failure shape changed

On a failed verification, the failure detail has moved from a reason property to failureType, and the VerificationFailedReason type has been removed. The value shape ({ type, message }) is unchanged.

Before:

if (!credential.verificationResult.verified) {
  console.log(credential.verificationResult.reason.type);
}

After:

if (!credential.verificationResult.verified) {
  console.log(credential.verificationResult.failureType.type);
}

Invalid-argument errors now use the InvalidParams error code

Invalid or malformed arguments are now rejected with an InvalidParams error code and a message describing the offending field, instead of a synchronous Error with a message of the form Invalid arguments for '<function>' function: .... Update any code that matched on the previous message.

Android now rejects unknown argument keys

Android rejects unrecognized keys in argument objects: any extra or misspelled field that is not part of a function's documented options fails with an InvalidParams error. iOS ignores unknown keys. Ensure argument objects contain only documented fields so behavior is consistent across platforms.

OfferedCredential.claims is now optional

claims on OfferedCredential (returned in credentials from discoverCredentialOffer) is now optional and is only present for offers that contain claim data. This aligns with the OID4VCI 1.0 specification. Handle the case where claims is absent rather than assuming an array is always present.

Credentials with empty claims are now rejected

Retrieving or adding a credential whose issuer signed data contains no namespaces, or a namespace with no claims, now fails with a decoding error instead of producing a credential with empty claims. Android already rejected these credentials, so behavior is now consistent across both platforms. This guarantees that MobileCredential.claims and MobileCredentialMetadata.claims are always populated. Handle the error where credentials are retrieved or added.

Pre-authorized issuance now sends the application client_id

Pre-authorized credential issuance flows now pass the application's client_id instead of a default identifier, so the holder is accurately represented when interacting with issuers. This improves compatibility with issuers applying stricter controls. Ensure your application has a valid configured client_id and that your issuers recognize it.

Renamed and removed exports

ExportChange
SessionStatusRenamed to SessionStatusErrorType. Also the type of PresentationSessionTerminationError.sessionStatus.
DateTimeRemoved. The validFrom, validUntil, expectedUpdate, and signed fields of ValidityInfo are now typed as Date.
NativeRetrieveCredentialsResponseRemoved. Use RetrieveCredentialsResponse, or the RetrieveCredentialItem, RetrieveCredentialSuccess, and RetrieveCredentialFailure types.
MobileCredentialHolderErrorType.ExistingProximityPresentationSessionNotFoundMoved to the new MobileCredentialHolderReactNativeErrorType enum. Update references to MobileCredentialHolderReactNativeErrorType.ExistingProximityPresentationSessionNotFound.
ProximityPresentationSessionTerminationErrorType.ExceptionRemoved. Handle unexpected presentation failures with your generic fallback strategy.
RetrieveCredentialsErrorTypes.UserAuthenticationRemoved. Use RetrieveCredentialsErrorTypes.UserAuthenticationFailed.

RetrieveCredentialsErrorTypes.UserAuthenticationFailed value changed

RetrieveCredentialsErrorTypes.UserAuthenticationFailed now has the value "UserAuthentication", previously "UserAuthenticationFailed". Code that compares the raw error string rather than the enum member must be updated.

Errors removed from function error types

Two errors are no longer raised and have been removed from the error types they appeared in:

  • sendOnlinePresentationResponse no longer returns AuthorizationResponseJWECreationFailed.
  • sendProximityPresentationResponse no longer returns UserAuthenticationUnrecoverableKey.

Features

SDK Backend support

Added support for an SDK Backend, which ties each SDK and app instance to a MATTR VII tenant. This lets you view details about registered and active app instances directly from your tenant for operational insight, and it establishes a remote management channel that we expect to extend in future releases. It is also what enables Wallet Attestation, described below, which cannot be used without it. On first initialization the SDK registers the app instance with the configured tenant and obtains a license. Subsequent initializations renew the existing license automatically. Network access is required when registration or renewal is performed.

  • A new optional platformConfiguration parameter has been added to initialize. It accepts:
    • tenantHost: base URL of the MATTR VII tenant (for example https://your-tenant.global).
    • applicationId: identifier of the MATTR VII holder application associated with this SDK.
    • externalReferenceId (optional): a developer-defined identifier used to correlate this app instance with a record in MATTR VII.
  • When platformConfiguration is provided, the SDK registers the app instance with your tenant and enables the SDK Backend. When it is omitted, the SDK skips registration and does not connect to a backend, so capabilities such as Wallet Attestation are unavailable.
  • The PlatformConfiguration type is now exported from the package.
await Holder.initialize({
  platformConfiguration: {
    tenantHost: "https://your-tenant.global",
    applicationId: "00000000",
  },
});

The SDK Backend is currently optional, but we expect to make it required in an upcoming release, so we recommend configuring it now to prepare. Refer to the SDK Backend guide for more details on how to enable and use this feature.

SDK Backend error handling

Initialization and the majority of public APIs can now surface SDK Backend failures as typed Result errors instead of throwing them.

  • initialize may now return InvalidLicense (the SDK license failed to validate or has expired) or FailedToRegister (registering the app instance with MATTR VII failed).
  • Both error codes map consistently across iOS and Android.

InvalidLicense may also be returned by the following public APIs when an SDK Backend is configured but a valid license is not present:

  • addCredential
  • getCredential
  • getCredentials
  • deleteCredential
  • generateDeviceKey
  • discoverCredentialOffer
  • createAuthorizationSession
  • retrieveCredentials
  • retrieveCredentialsUsingAuthorizationSession
  • createOnlinePresentationSession
  • createProximityPresentationSession
  • sendProximityPresentationResponse
  • getCurrentProximityPresentationSession
  • addTrustedIssuerCertificates
  • addTrustedVerifierCertificates
  • getTrustedIssuerCertificates
  • getTrustedVerifierCertificates
  • deleteTrustedIssuerCertificate
  • deleteTrustedVerifierCertificate

Wallet Attestation

Added support for Wallet Attestation, so you can claim credentials from issuers that restrict issuance to trusted wallet applications. When an issuer's authorization server advertises attestation-based client authentication, the SDK proves the application's authenticity automatically before claiming credentials. Wallet Attestation requires an SDK Backend, so a platformConfiguration must be passed to initialize.

  • DiscoveredCredentialOffer now exposes tokenEndpointAuthMethodsSupported (the client authentication methods supported by both the offer's authorization server and the SDK), along with authorizationServerIssuer and an optional nonceEndpoint. The tokenEndpoint, credentialEndpoint, and mdocIacasUri fields it already returned are now part of the public type.
  • retrieveCredentials and retrieveCredentialsUsingAuthorizationSession may now return:
    • InvalidCredentialOffer: the offer requires attestation but no platformConfiguration was provided, or the SDK supports none of the authorization server's advertised client authentication methods.
    • InvalidWalletAttestation: the authorization server rejected the attestation token.
  • When attestation fails for an individual credential, that credential's RetrieveCredentialFailure carries an invalidWalletAttestation error.

Refer to the Wallet Attestation guide for more details on how to enable and use this feature.

Expanded and consistent error types

Many public functions now surface errors as typed error codes that you can handle, where they previously surfaced as unrecognized thrown errors. The same error codes are now raised on both iOS and Android.

The following error codes were previously declared only as per-function string literals and are now members of MobileCredentialHolderErrorType:

  • FailedToRetrieveCredentials
  • FailedToDiscoverCredentialOffer
  • FailedToCreateAuthorizationSession
  • RedirectUriNotFound
  • InvalidTransactionCode
  • WebAuthenticationFailed
  • UnsupportedDeviceKeyAuthenticationPolicy
  • InvalidCredentialOffer

The per-function enums that reference these codes keep the same values:

  • DiscoverCredentialOfferErrorType
  • CreateAuthorizationSessionErrorType
  • RetrieveCredentialsErrorTypes

New MobileCredentialHolderErrorType members:

  • StorageInitialization: storage could not be initialized for the SDK.
  • SdkNotInitialized: the SDK has not been initialized.
  • DeviceKeyGenerationError: a device key could not be generated.
  • DeviceKeyNotDeleted: a device key could not be deleted from storage.
  • InvalidCertificate: a supplied certificate is not valid.
  • ClientMetadataServiceError: verifier client metadata could not be resolved during an online presentation.
  • ResponseModeNotSupported: the authorization request asked for an unsupported response mode.
  • FailedToCreateProximityPresentationSession: a proximity presentation session could not be created.
  • NfcDeviceEngagementNotFound: a proximity session was started with engagementFromNfc but no NFC device engagement was available.
  • ActivityRequired: an Android activity is required to complete the operation.
  • InvalidDeviceKeyAuthenticationPolicy: the supplied device key authentication policy is not valid.
  • DeviceKeyAuthenticationPolicyChangedException: the authentication policy of an existing device key has changed.
  • UserAuthenticationInvalidatedByBiometricEnrollment: the device key was invalidated because the biometrics enrolled on the device changed.
  • UserAuthenticationNotSupported: the requested user authentication configuration is not supported on this device.
  • MACAuthenticationUnavailableForAuthenticationPolicy: MAC authentication cannot be used with the credential's authentication policy.
  • CalledFromAppExtension: an API that is unavailable in app extensions was called from an iOS app extension.
  • OperationFailed: the operation failed for a platform-specific reason described in the error message.
  • RuntimeException: an unexpected or unrecoverable failure in the SDK.

New ProximityPresentationSessionErrorType members:

  • ResponseNotCreated
  • ResponseEncryptionFailed
  • SessionDecryption
  • PresentationNotCreated

The functions whose existing error types were extended are:

  • initialize
  • addCredential
  • getCredential
  • generateDeviceKey
  • discoverCredentialOffer
  • createAuthorizationSession
  • retrieveCredentials
  • retrieveCredentialsUsingAuthorizationSession
  • createOnlinePresentationSession
  • sendOnlinePresentationResponse
  • createProximityPresentationSession
  • sendProximityPresentationResponse

The seven functions that gained an error type for the first time are listed in Several functions now return a Result.

RuntimeException may be thrown by any function

RuntimeException is the catch-all for an unexpected or unrecoverable failure in the SDK. Because any function may throw it, it is not listed in each function's expected Result error type. Handle it with your generic fallback strategy and report it to MATTR.

Bug fixes

Security fixes

  • Authorization request objects are now validated against their iat, exp, and nbf claims on Android. The SDK previously performed no temporal validation, so a request object with an exp in the past could be replayed, and an iat in the future was accepted.
  • The OID4VP state parameter is now size limited on Android during online presentation. Arbitrarily large values were previously accepted and echoed back.
  • The Digital Credentials API origin on Android now uses an unpadded base64 encoded SHA-256 of the app signing certificate (android:apk-key-hash:<base64SHA256>) instead of hex, matching MATTR VII and reference wallet implementations. Verification previously failed because of the mismatch.

Proximity and NFC presentation

  • Fixed an issue on Android where NFC device engagement via negotiated handover could get stuck in an infinite loop on certain Samsung devices. The SDK now keeps the HCE session alive through internal activity transitions, guards against re-entrant engagement, and cancels stuck engagements when the NFC field is lost prematurely.
  • Improved UI stability on Android when the app is launched by an NFC interaction. The system no longer prompts the user to choose an application in most cases, addressing the multiple system prompts noted in the 9.0.0 known issues.
  • Fixed an issue on iOS where receiving a session status code, such as a session termination, emitted a spurious request-received callback and raised a redundant session terminated error. The session now terminates cleanly through the termination handler.
  • Hardened proximity presentation message handling on iOS. Empty BLE data chunks received during message reassembly are now discarded, preventing a crash when a peer sends malformed data.

Credential claiming

  • Fixed an issue on iOS where credential issuance web authentication was canceled when the app moved to the background. The authorization can now complete after returning to the app.
  • Fixed an issue on Android where credential offers were rejected if the authorization server metadata was missing token_endpoint_auth_methods_supported.
  • Fixed an issue on Android where OID4VCI metadata URIs were calculated incorrectly.
  • Fixed a crash on Android where oversized credential fields could exhaust memory during pre-authorized issuance. Such credentials are now rejected before they can exhaust memory.

Online presentation

  • Fixed a crash on Android during online presentation when the x5c header was stripped from a validly signed request object JWT. The malformed request is now rejected gracefully.
  • Fixed an issue on Android where a malformed authorization request JWS raised an unexpected error.

Storage, initialization, and authentication

  • Fixed an issue on iOS where an unretrievable database encryption key caused a StorageInitialization error after certain app lifecycle transitions.
  • Fixed an issue on iOS where switching an existing instance to a different app group did not remove the previous app group's data. The previous app group's data is now cleared when the app group is switched.
  • Error messages are now specific when a key protected by BiometryCurrentSet is invalidated by biometric re-enrollment on iOS. Signing with such a key previously surfaced an opaque CryptoTokenKit error.

Digital Credentials API

  • Fixed an issue on Android where requesting only an age_over_xx attribute during a Digital Credentials API flow showed no result on the consent screen instead of displaying the requested attribute before sharing.
  • Fixed an issue on Android where a Digital Credentials API presentation required every requested claim to be available. A credential that matches any single requested claim is now offered.
  • Fixed an issue on iOS where credentials added in the main app could be missing when a verifier requested them through the Digital Credentials API.

Known Issues

  • If your app includes its own iOS app extension, the internal storage location for iOS app extension logs has changed. Logs are still retrieved with the same getCurrentLogFilePath call and appGroup option, so no code changes are required, but any app extension logs written before upgrading, up to the 48 hour retention window, are no longer accessible after the upgrade. The location for main SDK logs is unchanged.

9.0.5

Bug fixes

  • Fixed an issue on iOS where restoring an app from a backup or moving it to a new device left the SDK unusable, with initialize always throwing StorageInitialization. The SDK now clears the unreadable storage and initializes cleanly. Credentials held before the restore must be reissued.
  • Fixed an issue on Android where instance IDs longer than 64 characters would prevent DCM from registering credentials.
  • Fixed an issue on Android where OID4VCI metadata URIs were calculated incorrectly.
  • Fixed an issue on Android where credential offers were rejected if the authorization server metadata was missing token_endpoint_auth_methods_supported.

9.0.4

Bug fixes

  • Fixed an issue on Android where the SDK could crash if DCM configuration cleanup failed. Cleanup errors are now caught and logged, allowing the host app to continue safely.

  • On iOS the SDK now recovers automatically from a storage key mismatch without data loss. A stored storage key could become stale for a number of reasons, leaving the SDK unable to initialize against existing credential data. This was most commonly observed during background prewarming, where the SDK could launch before the device’s first unlock and be unable to read existing keychain items. On initialization, the SDK now verifies the active storage key against an on-disk probe and, if the recorded key is stale, locates the correct key among the available keychain candidates and repairs the stored reference. If the probe cannot be read because of filesystem protection, StorageInitializedInBackground is thrown.

    Recovery sequence: the active storage key is verified by attempting to decrypt an encrypted on-disk probe. If the recorded key is stale, the SDK enumerates all available keychain candidates, identifies the one that successfully decrypts the probe, updates the stored key, and removes the stale entry.

9.0.3

Bug fixes

  • Added None as a DeviceKeyAuthenticationType option. This allows credentials to be generated or retrieved with no user authentication requirement, even when the SDK is initialized with userAuthenticationBehavior set to Always or OnDeviceKeyAccess. Pass { authenticationPolicy: { type: "None" } } to retrieveCredentials, retrieveCredentialsUsingAuthorizationSession, or generateDeviceKey to opt out of authentication for a specific device key.

9.0.2

Bug fixes

This release fixes the following iOS issues:

  • Fixed an issue where the SDK did not use the OID4VCI nonce endpoint during credential issuance when required by the issuer. The SDK now automatically fetches an issuer-provided nonce from nonceEndpoint (when it is advertised in the issuer metadata) and includes it in the device key proof-of-possession JWT, improving compliance with the OID4VCI specification.
  • Fixed an issue where calling discoverCredentialOffer would fail when credential metadata did not include any claims. The claims field is now treated as optional and defaults to an empty array when absent.
  • Fixed an issue where SDK initialization could fail on iOS devices due to inconsistent storage states, such as orphaned keychain keys after an app reinstall or transferred files without keys after device migration. The SDK now performs a preflight check and automatically recovers from these states.
  • Fixed an issue where SDK storage files and directories could be included in iOS device backups, resulting in encrypted data being backed up without the keys required to restore it. These files are now excluded from iCloud and local backups.
  • Fixed an issue where calling the destroy function did not fully remove persisted data on iOS devices. It now also deletes the database encryption key and storage key ID from the keychain, preventing orphaned keychain entries.

9.0.1

Bug Fixes

  • Fixed an issue where native binaries were not included in the builds published to NPM.

9.0.0

Breaking Changes

OpenID4VCI Version 1.0 Alignment

The SDK now aligns with the finalized OpenID for Verifiable Credential Issuance (OID4VCI) v1.0 specification, upgrading from draft-12.

  • The OfferedCredential type (in credentials from discoverCredentialOffer(..)) now includes a mandatory credentialConfigurationId property.
  • Compatibility with issuers implementing earlier OID4VCI draft versions is no longer guaranteed.

Simplified status check parameter

Replaced skipStatusCheck with fetchUpdatedStatusList to improve readability and reduce integration confusion:

  • true (default): Fetch the latest revocation status list from the server.
  • false: Use cached revocation status (if valid).

New error types for the initialize method

The initialize method can now return new error types to provide more specific feedback on initialization failures:

  • StorageInitializedInBackground
  • SdkInitialized
  • InvalidInstanceID

New error type in ProximityPresentationSessionTerminationErrorType

New Exception value was added to ProximityPresentationSessionTerminationErrorType. This is a fallback when an unexpected issue occurs during presentation.

Package path change

The package path for global.mattr.mobilecredential.common has been updated to global.mattr.mobilecredential.holder. Please ensure that you update your imports accordingly to avoid any issues with module resolution.

Xcode / Toolchain dependencies

The underlying iOS SDK is built with Xcode 26.0.0. Builds will fail on earlier toolchains (e.g. Xcode 16.4) and CI environments must be upgraded.

Features

Digital Credentials API (DC API) support

Added support for iOS’s Digital Credentials API, as defined in ISO/IEC 18013-7 Annex C (for iOS) and D (for Android). This update allows wallet apps using the Holder SDK to register stored credentials with the system, enabling them to appear in the DC API’s selector UI when a verifier requests credentials.

  • A new optional dcConfiguration parameter has been added to initialize which controls DC API behavior. You can set different options for iOS and Android.
  • When enabled, the SDK will automatically register credentials with the DC API after initialization and whenever credentials are added or removed. This means that credentials stored in the Holder SDK will be available for selection in the DC API without requiring additional integration work.

Logging in iOS app extensions

  • The SDK may now generate logs in an iOS app extension. getCurrentLogFile now includes an optional appGroup parameter. Use appGroup if you want to retrieve logs in the extension. On other platforms, getCurrentLogFile ignores appGroup.

mDoc Reader Authentication

Added support for mDoc Reader authentication as defined in ISO/IEC 18013-5:2021. The SDK can now be used to inspect the verifier authentication result and enable the user to decide whether to share credentials with an unauthenticated verifier.

  • Introduced a new VerifierAuthenticationResult type which represents the mDoc Reader Authentication result.
  • Introduced a new verifierAuthenticationResult property of type VerifierAuthenticationResult in MobileCredentialRequest.
    • This can result in a "trusted", "untrusted", or "unsigned" request.
  • Introduced a new VerifierInfo type which represents information regarding the root certificate used to verify the request.
  • Introduced a new VerifierAuthenticationError which represents the specific authentication error encountered during verification.
  • Introduced a new VerifierAuthenticationErrorType which represents the string literal that can be returned in the type field of VerifierAuthenticationError.

Device key authentication

Device key authentication offers fine-grained control over how each credential is protected and accessed on a user’s device. You can now specify a per-credential authentication policy that defines what user authentication (such as device credentials or biometrics) is required to claim and access a credential.

You can set authentication policy using three methods:

  • generateDeviceKey
  • retrieveCredentials
  • retrieveCredentialsUsingAuthorizationSession

All three methods generate device keys, with the latter two binding credentials keys. To set authentication policy, use the authenticationPolicy property as shown below:

const deviceKeyResult = await Holder.generateDeviceKey({
  issuer,
  audience,
  authenticationPolicy: {
    type: DeviceKeyAuthenticationType.BiometryCurrentSet,
  },
});

generateDeviceKey will store the key with the strictest authentication policy, BiometryCurrentSet. Any access to the key now requires biometric authentication. It will only allow the current set of biometrics too; changing biometric settings will invalidate the key.

The four authentication types are as follows, in order of strength:

  • DeviceCredential: As long as the user has unlocked their phone, they have access to the key. Any authentication method allowed
  • UserPresence: Requires PIN, fingerprint, etc. on each access to the key. Any authentication method allowed.
  • BiometryAny: Key is accessible only with biometric authentication, but changing or removing biometric settings is allowed.
  • BiometryCurrentSet: Key is accessible only with the current set of biometrics. Changing or removing a biometric will invalidate the key.

NFC proximity presentation support

The SDK now supports NFC device engagement for Android devices. This enables starting a proximity presentation session via the NFC channel. A session can now begin when the user taps their device on an NFC-enabled verifier terminal.

The very first step is to add this intent filter to the AndroidManifest.xml of your React Native app:

<intent-filter>
    <action android:name="global.mattr.mobilecredential.holder.NFC_RECEIVER_ACTIVITY" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

Then listen for NFC device engagement using setDeviceEngagementListener:

await Holder.setDeviceEngagementListener((error) => {
  if (error) {
    handleError(error);
    return;
  }

  // no error - can proceed to next step
});

Once the device engagement callback is invoked without error, start the presentation with engagementFromNfc set to true:

await Holder.createProximityPresentationSession({
  ...otherOptions,
  engagementFromNfc: true,
});

The SDK will invoke the listener upon successful NFC engagement, or if there was an error. If error is undefined, engagement was successful. The SDK has the device engagement information ready to go. You just need to start the presentation using engagementFromNfc: true.

Four new methods support NFC presentations:

  • setDeviceEngagementListener - adds or replace the current listener callback.
  • removeDeviceEngagementListener - removes the listener, if already set.
  • setNfcConfiguration and getNfcConfiguration - update or inspect settings related to NFC.

At this time, device engagement works while the app is in the foreground or background. Cold starts (when app is not running) are not currently supported. To start a presentation from NFC, users will first need to open your app, and then scan the verifier NFC's tag.

Status Lists Draft 14 Support

The SDK now supports the Token Status List Draft 14 specification while maintaining existing support for Draft 3.

  • Added support for the application/statuslist+cwt content type header as defined in Section 8.2 of the specification, while maintaining support for the existing mattr-statuslist+cwt type.
  • Added support for the updated status list URL format where status lists are represented as an array of URI strings rather than an array of objects.
  • The SDK respects rate limit response headers returned with HTTP 429 responses from status list endpoints, with a configurable default delay for rate-limited requests.

COSE algorithm updates

Updated COSE algorithms (as per RFC 9864) strengthen cryptographic compatibility and ensure continued compliance with evolving standards.

Known Issues

  • Some Samsung Android devices may display multiple system prompts when initiating an NFC credential sharing interaction if several installed apps can handle NFC intents. In these cases, the device may first show a “Select an app to use” dialog (e.g., Wallet vs. embedded tag handler) followed shortly by a “Choose an action” dialog from other NFC-capable apps (e.g., tag readers or transit apps). This behavior appears to be device- and firmware-specific and may interrupt the expected automatic credential sharing flow.

8.1.3

Bug fixes

iOS Platform

  • Improved early iOS app launch handling during SDK initialization. The SDK now probes Keychain accessibility before initialization proceeds, ensuring the storageKeyID can be loaded reliably before storage is accessed. This enhances protection against prewarming scenarios where Keychain items may be temporarily unavailable, reducing the likelihood of inconsistent storage state or unrecoverable initialization failures.
  • Resolved an issue that caused a crash when decoding DiscoveredCredentialOffer on devices running iOS 17.0 or earlier.
  • The SDK now supports ESP256, ESP384, and ESP512 signature algorithms, expanding compatibility with a broader range of ESP-based cryptographic operations.

8.1.2

Bug fixes

Android Platform

  • Resolved an issue that prevented retrieving credentials when a Branding.name value was not set.

8.1.1

Bug fixes

iOS Platform

  • Resolved an issue where calls to retrieveCredentialsUsingAuthorizationSession would fail on iOS devices running iOS 17.0 or earlier.

8.1.0

OID4VCI manual redirect support

This enhancement allows applications to implement the OpenID4VCI issuance workflow within embedded WebViews while maintaining full control over the redirect flow.

Applications can now:

  1. Call the new createAuthorizationSession method to initiate the flow. This returns an AuthorizationSession object containing both the authorizeUrl and codeVerifier properties.
  2. Load the returned authorizeUrl in a WebView to handle user authentication and consent.
  3. After successful authentication, capture the redirect using the configured redirectUri, then extract the authorization code from the returned URL.
  4. Complete the issuance workflow by calling the new retrieveCredentialsUsingAuthorizationSession method, passing in the AuthorizationSession and extracted authorization code.

Bug fixes

  • Remove usage of const from enums: UserAuthenticationBehavior and UserAuthenticationType

iOS Platform

  • Fixed an issue where the passcode fallback button was not displayed when biometric authentication failed and UserAuthenticationType was set to .biometricOrPasscode.
  • Fixed an issue where calling addCredential with a credential that could not be verified against any stored trusted issuer certificate incorrectly threw AddMobileCredentialError.certificateNotFound instead of AddMobileCredentialError.invalidCredential.

Android Platform

  • Fixed an issue where closing the embedded browser during the OpenID4VCI authorization flow caused retrieveCredentials to hang indefinitely.

8.0.0

Breaking changes

  • The React Native supported versions for the SDK is now 0.78.x or higher, including React Native’s New Architecture.

Spelling standardization change (UK → US English)

The following changes reflect the update of the SDK's spelling convention from UK English to US English.

  • Methods:
    • Renamed the initialise function to initialize.
    • Renamed the deinitialise function to deinitialize.
  • Errors:
    • Renamed MobileCredentialHolderError.AuthenticationCancelled to MobileCredentialHolderError.AuthenticationCanceled.
    • Renamed MobileCredentialHolderError.InvalidAuthorisationRequestUri to MobileCredentialHolderError.InvalidAuthorizationRequestUri.
    • Renamed MobileCredentialHolderError.InvalidAuthorisationRequestVerifiedByCertificate to MobileCredentialHolderError.InvalidAuthorizationRequestVerifiedByCertificate.
    • Renamed MobileCredentialHolderError.InvalidAuthorisationRequestVerifiedByDomain to MobileCredentialHolderError.InvalidAuthorizationRequestVerifiedByDomain.

Error handling consolidation

  • The getCredential method was updated as follows:
    • Added a new verification failure reason MobileCredentialVerificationFailureType.TrustedIssuerCertificateNotFound when the credential cannot be verified due to missing a matched trusted issuer certificate.

Features

  • Added a msoHash to the MobileCredential and MobileCredentialMetadata types. This property represents a hashed mobile security object, defined in ISO/IEC 18013-5:2021. Note that this property is distinct from the id property and should not be used in the getCredential method.

  • iOS Platform

    • The SDK now includes a check for empty CBOR arrays. Previously the SDK allowed credentials with an empty IssuerNamespaces field, but according to the Concise Data Definition Language (CDDL) specification defined in ISO/IEC 18013-5, this field must contain at least one entry. This update enforces that requirement, improving interoperability and ensuring issued credentials are standards-compliant.

7.0.0

Breaking changes

OID4VCI Pre-authorized Code flow support

The SDK now supports credential claiming using the OID4VCI Pre-Authorized Code Flow. Accordingly, the following changes have been introduced:

Method Signatures:

  • The retrieveCredentials method now accepts:
    • The original offer URL as a String, instead of the previous CredentialOfferResponse type for the credentialOffer parameter
    • An optional transactionCode
    • The autoTrustMobileIaca and redirectUri parameters are now set in the initialise method, whereas previously they were parameters of retrieveCredentials.
  • The following properties no longer need to be exposed in the reponse of discoverCredentialOffer and are now managed interally to the SDK:
    • authorizeEndpoint,
    • tokenEndpoint,
    • credentialEndpoint,
    • mdocIacasUri
  • New repsonse parameters added to discoverCredentialOffer:
    • TransactionCode struct

User authentication configuration

The initialise method now allows configuring how biometric authentication is performed. To allow this the following changes were introduced:

  • Introduced a new UserAuthenticationConfiguration object:
    • UserAuthenticationConfiguration.userAuthenticationBehavior supports the following options:
      • UserAuthenticationBehavior.Always requires user authentication for all supported operations
      • UserAuthenticationBehavior.None no user authentication is required
      • UserAuthenticationBehavior.OnDeviceKeyAccess requires user authentication when presenting or issuing a credential
      • UserAuthenticationBehavior.OnInitialise requires user authentication when initialising the SDK
    • UserAuthenticationConfiguration.userAuthenticationType is iOS only and supports the following options:
      • UserAuthenticationType.BiometricOnly only biometric authentication is allowed
      • UserAuthenticationType.BiometricOrPasscode authentication with either biometrics or device passcode
  • Replaced the userAuthRequiredOnInitialise boolean parameter in the initialise method with userAuthenticationConfiguration of type UserAuthenticationConfiguration.
  • Renamed the MobileCredentialHolderErrorType.UserAuthenticationOnInitChanged error type to MobileCredentialHolderErrorType.UserAuthenticationConfigurationChanged.
  • Renamed CredentialIssuanceOptions to CredentialIssuanceConfiguration

Error handling consolidation

In order to provide a more cohesive and manageable error handling in the OID4VCI flow, we have consolidated some error cases into broader ones. This change aims to make it easier for developers to handle errors consistently. Below is a summary of the changes:

  • discoverCredentialOffer no longer throws the following errors:
    • DiscoverCredentialOfferErrorType.CredentialOfferNotFound
    • DiscoverCredentialOfferErrorType.SupportedCredentialsNotFound
    • DiscoverCredentialOfferErrorType.CredentialOfferNotInCredentialIssuerMetadata
    • DiscoverCredentialOfferErrorType.IssuerMetadataServiceError
  • Instead, these errors were consolidated into:
    • DiscoverCredentialOfferErrorType.FailedToDiscoverCredentialOffer

**To see the full list of errors that discoverCredentialOffer may throw, refer to this method in the SDK documentation. **


  • retrieveCredentials no longer throws the following errors:
    • RetrieveCredentialsErrorTypes.AuthCodeNotFound
    • RetrieveCredentialsErrorTypes.AuthenticationFailed
    • RetrieveCredentialsErrorTypes.CertificateNotFound
    • RetrieveCredentialsErrorTypes.DeviceKeyGenerationError
    • RetrieveCredentialsErrorTypes.GenerateAuthorisationUrlFailed
  • Instead, these errors have been added:
    • RetrieveCredentialsErrorTypes.RedirectUriNotFound
    • RetrieveCredentialsErrorTypes.InvalidTransactionCode
    • RetrieveCredentialsErrorTypes.WebAuthenticationFailed
    • RetrieveCredentialsErrorTypes.FailedToDiscoverCredentialOffer

Enhancements

  • Introduced support for future dated credentials. The addCredential method can now be used to add credentials with a future validity period to the storage.
  • [iOS] The SDK's storage data protection class was changed from C (Protected Until First User Authentication) to B (Protected Unless Open). See Apple Platform Security forum for details.
  • The SDK no longer checks the signature algorithm when adding verifier certificates. This aligns with ISO/IEC 18013-5:2021, which does not specify required algorithms for reader root certificates.

Bug fixes

  • Fixed an issue where special characters in credential offers were escaped twice.
  • Resolved a potential crash when establishing a BLE connection.
  • Fixed an issue where the browser would retain focus after authenticating during credential retrieval via OpenID4VCI.
  • Fixed validation for ES384 and ES512 signatures.
  • Enabled using RSA as a digital signature algorithm for Reader Authentication root certificates.

6.0.0

Features

First GA release as a standalone SDK.

How would you rate this page?

On this page