Wallet Integration

This guide explains how to configure the Wallet Service to obtain and use client attestations when requesting credentials from issuers that require attestation-based client authentication.

Overview

The wallet integration involves two steps:

  1. Obtain an attestation – The wallet requests an attestation JWT from a Client Attestation Service
  2. Use the attestation – The wallet includes the attestation in credential requests to issuers

Prerequisites

Before configuring wallet attestation:

  1. Wallet Service – An existing Wallet Service in your tenant
  2. Client Attestation Service – A configured Client Attestation Service in your tenant
  3. Wallet Key – A key in the wallet's KMS that will be used as the instance key

First, add the Client Attestation Service as a dependency of the Wallet Service.

CURL

Endpoint: /v1/{target}/wallet-service-api/dependencies/add | API Reference

Example Request

curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/wallet-service-api/dependencies/add' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: text/plain' \
  -d 'waltid.tenant1.client-attester1'

Path Parameters

  • orgID – Your organization's Base URL
  • target – The wallet service target ({organizationID}.{tenantID}.{walletServiceID}), e.g. waltid.tenant1.wallet1

Body

The resource identifier of the Client Attestation Service to link, e.g. waltid.tenant1.client-attester1


Response Codes

  • 201 – Dependency added successfully

Obtain a Client Attestation

The wallet must obtain an attestation JWT before it can request credentials from issuers that require attestation. The attestation is stored in the wallet's resource tree and can be reused until it expires.

CURL

Endpoint: /v1/{target}/wallet-service-api/client-attestation/obtain

Example Request

curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/wallet-service-api/client-attestation/obtain' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "clientAttesterServiceRef": "waltid.tenant1.client-attester1",
  "instanceKeyReference": "waltid.tenant1.kms1.wallet_key"
}'

Body

{
  "clientAttesterServiceRef": "waltid.tenant1.client-attester1",
  "instanceKeyReference": "waltid.tenant1.kms1.wallet_key"
}

Path Parameters

  • orgID – Your organization's Base URL
  • target – The wallet service target ({organizationID}.{tenantID}.{walletServiceID}), e.g. waltid.tenant1.wallet1

Body Parameters

  • clientAttesterServiceRef: resourceIdentifier – Reference to the Client Attestation Service that will issue the attestation
  • instanceKeyReference: resourceIdentifier – Reference to the wallet's instance key in the KMS. The public key will be embedded in the attestation's cnf.jwk claim.

Response

{
  "clientAttestationJwt": "eyJhbGciOiJFUzI1NiIsInR5cCI6Im9hdXRoLWNsaWVudC1hdHRlc3RhdGlvbitqd3QifQ...",
  "expiresAt": 1715270400
}

Response Fields

  • clientAttestationJwt: String – The signed attestation JWT
  • expiresAt: Long – Unix timestamp when the attestation expires

Response Codes

  • 200 – Attestation obtained successfully
  • 400 – Invalid request
  • 404 – Client Attester Service or key not found

Check Current Attestation

You can retrieve the wallet's current stored attestation to check its status or expiration.

CURL

Endpoint: /v1/{target}/wallet-service-api/client-attestation/current

Example Request

curl -X 'GET' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/wallet-service-api/client-attestation/current' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}'

Path Parameters

  • orgID – Your organization's Base URL
  • target – The wallet service target ({organizationID}.{tenantID}.{walletServiceID}), e.g. waltid.tenant1.wallet1

Response

{
  "clientAttestationJwt": "eyJhbGciOiJFUzI1NiIsInR5cCI6Im9hdXRoLWNsaWVudC1hdHRlc3RhdGlvbitqd3QifQ...",
  "expiresAt": 1715270400,
  "instanceKeyId": "waltid.tenant1.kms1.wallet_key"
}

Response Codes

  • 200 – Current attestation returned
  • 404 – No attestation found for this wallet

Use Attestation When Receiving Credentials

When requesting credentials from an issuer that requires attestation, set useClientAttestation: true in the receive request. The wallet will automatically:

  1. Load the stored attestation
  2. Build a fresh PoP JWT signed with the instance key
  3. Include both in the token request headers
CURL

Endpoint: /v2/{target}/wallet-service-api/credentials/receive/pre-authorized

Example Request

curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v2/{target}/wallet-service-api/credentials/receive/pre-authorized' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "offerUrl": "openid-credential-offer://issuer.example.org/issue/?credential_offer_uri=...",
  "keyReference": "waltid.tenant1.kms1.wallet_key",
  "useClientAttestation": true
}'

Body

{
  "offerUrl": "openid-credential-offer://issuer.example.org/issue/?credential_offer_uri=...",
  "keyReference": "waltid.tenant1.kms1.wallet_key",
  "useClientAttestation": true
}

Body Parameters

  • offerUrl: String – The credential offer URL from the issuer
  • keyReference: resourceIdentifier – Reference to the wallet's key (must match the instance key used when obtaining the attestation)
  • useClientAttestation: Boolean – When true, the wallet includes attestation headers in the token request

Attestation Lifecycle

Expiration

Attestations have a configurable validity period (default: 24 hours). When an attestation expires:

  1. The wallet will receive an error when trying to use it
  2. The issuer may return a use_fresh_attestation error code
  3. The wallet must obtain a new attestation before retrying

Refresh Strategy

For production deployments, consider implementing an attestation refresh strategy:

  • Proactive refresh – Obtain a new attestation before the current one expires
  • Reactive refresh – Obtain a new attestation when the issuer returns use_fresh_attestation

Error Handling

ErrorDescriptionResolution
use_fresh_attestationAttestation has expiredObtain a new attestation and retry
invalid_clientAttestation signature verification failedCheck that the issuer trusts the attester's key
invalid_clientPoP signature verification failedEnsure the wallet is using the correct instance key
invalid_clientPoP aud mismatchVerify the issuer's RFC 8414 issuer identifier URL

Next Steps

Last updated on May 8, 2026