light-mode-image
Learn
Guides

Wallet Attestation

Learn how Wallet Attestation works in MATTR Holder SDKs to enable credential claiming from issuers that require trusted wallet applications.

Overview

Wallet Attestation lets your holder application prove it is a trusted, verified wallet so that issuers who require it will release credentials to you. When an issuer requires Wallet Attestation, your application must cryptographically prove its authenticity before it can claim credentials.

Your wallet is identified to issuers using a client identifier (clientId) you agree on with each issuer, which lets them recognise your wallet as an approved, trusted origin on their curated list. The Holder SDK automatically generates, manages, and presents the Wallet Attestation proof whenever a credential request occurs, so supporting this capability adds no extra code to your claiming flow and no extra friction for your users — everything happens in the background, and credential claiming looks and feels the same as before. The main work is the one-time coordination with each issuer to establish trust, described in Setting up Wallet Attestation.

This mechanism is valuable when:

  • Enforcing wallet policies: Issuers can ensure that only authorized and trusted wallet applications receive their credentials.
  • Protecting against unauthorized access: Credential theft is prevented by verifying the wallet's identity before issuance.
  • Leveraging platform-based attestation: Platform-specific security mechanisms (such as iOS App Attestation and Android Key Attestation) are used to authenticate app instances with the MATTR VII tenant, ensuring that only trusted wallet instances receive attestation proofs for use with issuers.

For a detailed technical breakdown of Wallet Attestation from an issuer's perspective, including attestation modes, JWT structures, and certificate trust chains, see Wallet Attestation in the Issuance documentation.

What this means for your team

Supporting Wallet Attestation in your wallet involves more than just the integration code:

  • For policy makers: Wallet Attestation is how issuers decide which wallet applications can receive their credentials. Establishing your wallet as a recognised, trusted application — through the root certificate you share and the client identifier you agree on — is what gets your users' credentials released by issuers that enforce these rules.
  • For product managers and designers: Your existing claiming flows and user experiences stay the same. Attestation proofs are securely generated and presented in the background, so users gain the trust benefits without any added friction or change to how they claim credentials.
  • For solution architects: Integrate the Holder SDK with your MATTR VII tenant and wallet identity. Securely manage identities and cryptographic keys, and design for multi-tenant separation, high availability, observability, error handling, and monitoring of attestation outcomes.

Standards and specifications

Wallet Attestation in MATTR VII is based on the following standards:

How it works

At a high level, getting your wallet recognised and claiming credentials from an issuer that requires Wallet Attestation involves four steps:

  1. Share and onboard the root certificate: You create a Holder root CA certificate on your MATTR VII tenant — this is your Wallet Attestation root — and share it with the issuer, who onboards it as the trust anchor for your wallet application. This is a one-time, out-of-band setup per issuer.
  2. Configure and operate: The issuer configures their issuance flows to require Wallet Attestation for your wallet, registered against the client identifier you agree on.
  3. Retrieve a credential as usual: When a user claims a credential, the Holder SDK automatically obtains or refreshes a Wallet Attestation proof — bound to that specific wallet instance — and sends it to the issuer as part of the standard credential retrieval flow.
  4. Verify and issue: The issuer validates the proof against your onboarded root CA certificate. If it is valid and your wallet is approved, the credential is issued and stored in the app; otherwise the SDK surfaces an error.

Steps 1 and 2 are the one-time coordination covered in Setting up Wallet Attestation. Steps 3 and 4 are handled automatically by the SDK at claim time and require no additional code from you. The rest of this section explains the underlying interaction in detail.

High-level overview of the Wallet Attestation flow between the holder's MATTR VII tenant, the wallet app, and the issuer's MATTR VII tenant

The following diagram illustrates the interaction between the Holder SDK, the MATTR VII tenant, and the issuer.

At the protocol level, the Wallet Attestation proof is carried as an OAuth client attestation JWT (defined in OAuth 2.0 Attestation-Based Client Authentication) combined with a DPoP proof. In the descriptions below, "client attestation JWT" refers to the token that conveys the Wallet Attestation to the issuer.

  1. Retrieve the credential offer: The Holder SDK retrieves the credential offer from the issuer. This offer includes a reference to the issuer's metadata endpoint.
  2. Check issuer metadata for attestation requirements: The Holder SDK fetches the issuer's metadata. If the metadata specifies that the issuer requires Wallet Attestation to issue credentials, the SDK proceeds with the attestation flow. If not, credential claiming continues without attestation.
  3. Request a Wallet Attestation token from the tethered tenant: The Holder SDK automatically makes a request to the MATTR VII tenant it is tethered to, passing the identifiers of the Holder Application configuration that were declared during SDK initialization.
  4. The MATTR VII tenant validates and returns the Wallet Attestation token: The MATTR VII tenant recognizes the app as a registered instance of the configured Holder Application. Assuming SDK Tethering is correctly set up, the tenant returns a signed client attestation JWT that carries the Wallet Attestation proof.
  5. Generate a DPoP proof and present attestation to the issuer: The Holder SDK generates a DPoP proof locally and includes both the client attestation JWT and the DPoP proof when requesting the credential from the issuer. Together these two values form the complete Wallet Attestation presented to the issuer. No additional code is required from the holder application developer.
  6. Issuer validates and issues the credential: The issuer validates the Wallet Attestation (client attestation JWT + DPoP proof), confirms that all requirements are met, and issues the credential to the holder application.

Setting up Wallet Attestation

Complete the following steps to enable Wallet Attestation in your holder application.

Configure SDK Tethering

Set up SDK Tethering 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.

  1. Create Holder Applications on your MATTR VII tenant for each platform target (iOS and Android).
  2. Initialize the SDK with the correct platformConfiguration including the tenant URL and the identifiers of the Holder Application you created.

Create and activate a Holder root CA certificate

Your tethered 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:

  1. 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.

  2. 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.

  3. Align on the client identifier: The clientId you configure on your Holder Application is included as the sub claim 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 clientId for 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, one clientId, 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-wallet while another requires partner-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 distinct clientId and 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.

Understanding issuer requirements

Whether an issuer requires Wallet Attestation from your wallet depends on how they have configured their trusted wallets, not just on what their public metadata advertises.

  • Issuer metadata (the OID4VCI .well-known endpoint) declares which authentication methods the issuer supports at a tenant level. For example, the issuer may advertise both attest_jwt_client_auth_dpop and none as supported methods.
  • Per-client configuration determines what is required for any specific wallet. The issuer configures this in their trusted wallet list, associating a client identifier with a specific authentication method.

Your wallet cannot determine from public metadata alone whether Wallet Attestation is required for your specific wallet application. The issuer communicates this requirement to you as part of the onboarding process. In practice:

  • If the issuer has configured your application with Wallet Attestation required, the SDK must present a valid attestation proof or credential claiming will fail.
  • If the issuer has configured your application without Wallet Attestation, the SDK may still send an attestation proof (if it detects attestation support in the issuer metadata), and the issuer will simply ignore it.
  • If the issuer does not support Wallet Attestation at all (not advertised in metadata), the SDK does not send an attestation proof.

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:

Request body
{
    "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

On this page