How to set up Wallet Attestation
Configure the SDK Backend, create a Holder root CA certificate, and coordinate with each issuer to enable Wallet Attestation in your holder application.
Wallet Attestation lets your holder application prove it is a trusted wallet to issuers that require it. For how the mechanism works and why issuers use it, see the Wallet Attestation overview. This guide covers the one-time setup: configuring the SDK Backend, creating a Holder root CA certificate, and coordinating with each issuer.
Setting up Wallet Attestation
Complete the following steps to enable Wallet Attestation in your holder application.
Configure the SDK Backend
Set up an SDK Backend to connect the Holder SDK to your MATTR VII tenant:
Creating a Holder Application is currently not available in the MATTR Portal and must be performed using the MATTR VII API. Portal support will be added in the near future.
- Create Holder Applications on your MATTR VII tenant for each platform target (iOS and Android).
- Initialize the SDK with the correct
platformConfigurationincluding the tenant URL and the identifiers of the Holder Application you created.
Create and activate a Holder root CA certificate
Your backend MATTR VII tenant must have an active Holder root CA certificate. This root CA is used to sign Wallet Attestation signers, which in turn sign the client attestation JWTs presented to issuers, forming a chain of trust.
MATTR VII supports two types of Holder root CA certificates:
- Managed: MATTR VII generates and manages the root certificate and its private key on your behalf. Wallet attestation signers are auto-provisioned when needed.
- Unmanaged (external): You supply your own root CA in PEM format. You are responsible for signing and uploading wallet attestation signer certificates.
For step-by-step instructions on creating and activating a Holder root CA, see the Holder certificates guide.
Coordinate with the issuer
Wallet Attestation requires an out-of-band coordination process between you and each credential issuer. You must complete the following before your wallet can claim credentials from issuers that require Wallet Attestation:
-
Confirm the issuer's requirements: Verify with the issuer whether Wallet Attestation is required. See Understanding issuer requirements for details on how issuer-side configuration works.
-
Share your Holder root CA certificate: Provide the public certificate of your root CA to the issuer (for example, via a secure channel or as part of a business onboarding process). The issuer uses this certificate so they can validate the attestation proof chain your SDK presents.
-
Align on the client identifier: The
clientIdyou configure on your Holder Application is included as thesubclaim in the wallet attestation JWT and is the value the issuer sees when your wallet claims a credential. The issuer must have this exact value registered against your wallet (with Wallet Attestation required) in their trusted wallet list. If the value your wallet presents and the value the issuer has registered do not match, the issuer rejects the attestation proof and credential claiming fails. See Agreeing on a client identifier for how to coordinate this value and why agreeing on it early matters.
Agreeing on a client identifier
The Wallet Attestation proof already tells the issuer which trusted wallet application is requesting
the credential. That proof is what cryptographically establishes your wallet's authenticity. The
clientId carries no additional product capability on top of this. It exists because the underlying
OAuth 2.0 Attestation-Based Client Authentication
specification requires every client to identify itself with a client_id. MATTR VII supports it so
your wallet interoperates with any spec-compliant issuer, but the choice of value is something you
and each issuer must agree on out of band.
There are two ways this coordination plays out:
-
You define the client identifier (recommended): You choose a single
clientIdfor your wallet application (for example,mattr-wallet), configure it on your Holder Application, and share it, together with your Holder root CA certificate, with each issuer during onboarding. Every issuer registers that same value, so your wallet presents one consistent identity everywhere. This keeps your integration simple: one Holder Application, oneclientId, and no per-issuer bookkeeping. -
The issuer assigns the client identifier: Some issuers insist on assigning their own value (for example, one issuer registers your wallet as
mattr-walletwhile another requirespartner-wallet-42). Because the value your wallet presents must match what each issuer has registered, supporting issuer-assigned identifiers means maintaining a separate Holder Application for each distinctclientIdand tracking which issuer expects which value. This adds operational overhead and is best avoided where possible.
Recommendation: Wherever you can, agree on a single clientId that you define and ask each
issuer to register it as-is. Raising this early in onboarding, before the issuer has provisioned
your wallet in their trusted wallet list, saves you from managing multiple Holder Applications and
per-issuer client identifier mappings later.
Important for existing integrations: If you already have a client_id registered with an
issuer from a pre-Wallet Attestation integration, we recommend registering a new client_id
for your Wallet Attestation-enabled app rather than reusing the existing one. See
Migrating to Wallet Attestation for details.
Once these steps are complete, the SDK handles all Wallet Attestation interactions automatically whenever an issuer requires it during credential claiming.
Migrating to Wallet Attestation
When you enable Wallet Attestation, your SDK uses a different client authentication method
(attest_jwt_client_auth_dpop instead of none). If older app versions that do not support
Wallet Attestation share the same client identifier, and the issuer configures that client identifier to
require attestation, those older versions will fail to claim credentials.
If your holder application is already integrated with an issuer that does not require Wallet Attestation, it is recommended to use a new client identifier to migrate safely without breaking existing app versions, as described in the following steps.
Register a new client identifier with the issuer
Coordinate with the issuer to register a new client identifier (for example, my-wallet-client-v2) that will
be associated with Wallet Attestation. The issuer adds this new client identifier to their trusted
wallet list with Wallet Attestation required, alongside your existing client identifier which continues
to work without attestation.
Configure your Holder Application with the new client identifier
When creating or updating your Holder Application on your MATTR VII tenant, set the clientId
field to the new value you registered with the issuer:
{
"name": "My iOS Holder Application",
"clientId": "my-wallet-client-v2",
"type": "ios",
"bundleId": "com.yourcompany.holderapp",
"teamId": "YOUR_APPLE_TEAM_ID",
"maxTimeOfflineInSecs": 864000,
"appAttest": {
"required": true,
"environment": "production"
}
}Release the updated app
Publish the new version of your app that supports Wallet Attestation. This version uses the new client identifier and presents Wallet Attestation proofs to issuers that support it. Existing app versions continue to use the original client identifier and operate without attestation.
Retire the old client identifier
Once you are confident that enough users have migrated to the new app version, coordinate with the issuer to remove the old client identifier from their trusted wallet list. This completes the migration and ensures all active wallet instances use Wallet Attestation.
How would you rate this page?
Last updated on
Overview
Learn how Wallet Attestation works in MATTR Holder SDKs to enable credential claiming from issuers that require trusted wallet applications.
PKI and key management
How MATTR VII's Public Key Infrastructure and key management underpin holding, the certificate types involved, key protection options, and considerations for planning a deployment.