Skip to main content

WUA explained: how a wallet proves itself to an issuer

A Wallet Unit Attestation, WUA, is what an EUDI Wallet shows a PID Provider or Attestation Provider during issuance to prove it is genuine. It is not one document but two, both signed by the Wallet Provider: a Wallet Instance Attestation (WIA) about the wallet app, and a Key Attestation (KA) about the secure storage of the keys a credential will be bound to.

The problem a WUA solves

An issuer about to hand a PID or a company registration credential to a wallet has no built-in way to tell a certified EUDI Wallet from a modified app or a script replaying an authorization flow. Nor can it see whether the key the credential will be bound to lives in certified secure hardware, or in ordinary storage it could be copied from.

The WUA closes both gaps. The Wallet Provider vouches for the app through the WIA and for the key storage through the Key Attestation. The issuer checks both before issuing, and keeps checking their revocation status afterwards, so it can revoke what it issued if the wallet or its key storage is later found to be compromised.

A WUA is used only during issuance. The ARF forbids a Wallet Unit from presenting a WIA or Key Attestation to a Relying Party, which keeps wallet details out of every presentation.

The actors and who trusts whom

Five roles are involved, and only four of them ever handle a WUA. The WSCD (Wallet Secure Cryptographic Device) or a keystore generates and guards the keys, the Wallet Provider vouches for the app and the keys, and the issuer relies on that instead of assessing the wallet itself.

Wallet Provider

Signs WIAs and Key Attestations after checking the app and the key storage, and runs the Status Lists for both

Wallet Unit

Sends a WIA and a Key Attestation to the issuer during issuance, and uses each for one issuance only

WSCD or keystore

Generates and holds the private keys a Key Attestation describes

PID Provider or Attestation Provider

Verifies the WIA and Key Attestation, binds the credential to an attested key, and keeps checking both for revocation

Relying Party

Never receives a WUA. It checks the credential, its device binding and its revocation status instead

Issuers trust a WUA because the Wallet Provider’s signing certificate, sent in the x5c header, chains to a trust anchor on the Trusted List for Wallet Providers. The Wallet Solution itself is certified by a conformity assessment body, and the WIA carries that certification information.

Two attestations under one name

TS3, the EUDI technical specification for WUAs, splits the attestation in two because the app and the key storage are different things, checked at different endpoints and revoked for different reasons.

Wallet Instance Attestation (WIA)

Attests
The integrity of the Wallet Instance, meaning the app
Sent to
The Authorization Server, in the Pushed Authorization Request and the Token Request
Lifetime
Less than 24 hours
Revocation
client_status: the revocation state of this Wallet Instance
Needed for
Every issuance, device-bound or not

Key Attestation (KA)

Attests
That one or more keys were generated in and are held by a named WSCD or keystore, and how well that storage resists attack
Sent to
The Credential Issuer, inside the proofs of the Credential Request
Lifetime
Chosen by the Wallet Provider, and may be longer than a WIA
Revocation
key_storage_status: the revocation state of the WSCD or keystore
Needed for
Device-bound credentials only, including every PID

Both are JWTs signed by the Wallet Provider with ES256, ES384 or ES512. A Key Attestation is used for one issuance only, and a WIA is never reused towards a different issuer, so issuers cannot link requests from the same wallet.

How a Wallet Unit obtains its WIAs and Key Attestations

TS3 leaves this step to each Wallet Provider, since it happens inside one wallet product. The ARF only requires the Wallet Provider to verify the app’s integrity before signing a WIA, and to verify that the attested private keys really sit in the named WSCD or keystore before signing a Key Attestation. A typical flow, using platform attestations such as Google Play Integrity or Apple DeviceCheck as evidence, looks like this.

1. Wallet Unit

Asks the WSCD or keystore to generate key pairs

generate keys

2. WSCD or keystore

Returns the public keys, with platform evidence of where they were generated

public keys + evidence

3. Wallet Provider

Checks the app’s integrity and the key evidence, then signs WIAs and Key Attestations

WIA + KA

4. Wallet Unit

Keeps a supply of fresh WIAs and Key Attestations, and uses a new one for each issuance

What a WIA and a Key Attestation contain

Neither carries an iss claim: the issuer identifies the Wallet Provider from the signing certificate in the x5c header. The examples below are decoded, with header and payload separated by a dot.

Wallet Instance Attestation

{
  "typ": "oauth-client-attestation+jwt",
  "alg": "ES256",
  "x5c": ["MIIC..."]
}.{
  "sub": "https://wallet.example.eu",
  "wallet_name": "ExampleWallet-mobile",
  "wallet_version": "2.3.0",
  "wallet_link": "https://wallet.example.eu/about",
  "wallet_solution_certification_information": "https://wallet.example.eu/certification/2-3-0",
  "exp": 1789329600,
  "client_status": {
    "status": {
      "status_list": { "idx": 48213, "uri": "https://wallet.example.eu/status/wia/17" }
    },
    "exp": 1791936000
  },
  "cnf": {
    "jwk": { "kty": "EC", "crv": "P-256", "x": "...", "y": "..." }
  }
}
FieldWhat it tells the issuer
typ / x5cThat this is a client attestation, and the Wallet Provider’s certificate chain to check against the Trusted List
subThe wallet type, the same for every installation, so it cannot be used to track a user
wallet_name / wallet_versionThe Wallet Solution as listed on the Trusted List, and its version
wallet_solution_certification_informationWho certified the Wallet Solution; the exact content is still to be defined
expTechnical expiry, less than 24 hours after the integrity check
client_statusA Status List entry for this Wallet Instance, and the date until which the Wallet Provider keeps it up to date
cnfThe key that signs the proof of possession sent along with the WIA

Key Attestation

{
  "typ": "key-attestation+jwt",
  "alg": "ES256",
  "x5c": ["MIIC..."]
}.{
  "iat": 1789257600,
  "exp": 1791936000,
  "certification": "https://wallet.example.eu/certification/wscd/secure-element",
  "key_storage": ["iso_18045_high"],
  "user_authentication": ["iso_18045_high"],
  "attested_keys": [
    { "kty": "EC", "crv": "P-256", "x": "...", "y": "..." },
    { "kty": "EC", "crv": "P-256", "x": "...", "y": "..." }
  ],
  "key_storage_status": {
    "status": {
      "status_list": { "idx": 3, "uri": "https://wallet.example.eu/status/ka/1" }
    },
    "exp": 1794614400
  }
}
FieldWhat it tells the issuer
typ / x5cThat this is a key attestation, and the Wallet Provider’s certificate chain to check against the Trusted List
iat / expWhen it was issued and when it technically expires
attested_keysPublic keys whose private keys the WSCD or keystore generated and holds; several keys allow batch issuance
key_storage / user_authenticationHow well the storage, and the user authentication that unlocks the keys, resist attack; a WSCD is always iso_18045_high for both
certificationThe certification of the WSCD or keystore, from which the issuer can tell whether it is a WSCD
key_storage_statusA Status List entry for the WSCD or keystore, and the date until which the Wallet Provider keeps it up to date
nonceThe issuer’s c_nonce, present only when the Key Attestation is sent as an attestation proof

Where a WUA travels during OpenID4VCI issuance

The two attestations go to different places. The WIA authenticates the wallet as an OAuth client at the Authorization Server. The Key Attestation goes to the Credential Issuer with the request for the credential itself.

Authorization Server receives the WIA

OAuth-Client-AttestationOAuth-Client-Attestation-PoP
  • The WIA signature chains to the Trusted List for Wallet Providers
  • The WIA has not expired and the Wallet Instance is not revoked
  • The proof of possession is signed with the key in the WIA’s cnf claim

Credential Issuer receives the Key Attestation

proofs.jwt[].key_attestationproofs.attestation
  • The Key Attestation signature chains to the Trusted List for Wallet Providers
  • The issuer’s fresh c_nonce is in the jwt proof or in the Key Attestation itself
  • The WSCD or keystore is not revoked, and the credential is bound to one of the attested_keys

Pushed Authorization Request with the WIA

POST /par HTTP/1.1
Host: issuer.example.eu
Content-Type: application/x-www-form-urlencoded
OAuth-Client-Attestation: <WIA JWT>
OAuth-Client-Attestation-PoP: <PoP JWT signed with the WIA cnf key>

response_type=code
&client_id=https%3A%2F%2Fwallet.example.eu
&scope=company_registration
&code_challenge=<S256 challenge>
&code_challenge_method=S256
&redirect_uri=<wallet redirect URI>

The client_id matches the sub of the WIA. The Token Request carries the same two headers. Because the Credential Issuer never sees the WIA, the Authorization Server has to pass its client_status on, for example inside the access token.

Credential Request with the Key Attestation

POST /credential HTTP/1.1
Host: issuer.example.eu
Authorization: DPoP <access_token>
DPoP: <DPoP proof JWT>
Content-Type: application/json

{
  "credential_configuration_id": "company_registration",
  "proofs": {
    "jwt": ["<proof JWT: Key Attestation in its key_attestation header, signed with attested_keys[0]>"]
  }
}

With the attestation proof type, the request carries "proofs": { "attestation": ["<Key Attestation JWT>"] } instead. There is no proof of possession then: the Wallet Unit passes the issuer’s c_nonce to the Wallet Provider, which puts it in a freshly signed Key Attestation.

The WUA lifecycle

A WUA is short-lived and single-use on purpose, but the revocation information behind it outlives the token itself. The first three stages are routine; the fourth only happens when something goes wrong.

1. Issuance

The Wallet Provider signs WIAs and Key Attestations after its integrity and key storage checks

2. Single use

Each one serves a single issuance, so the Wallet Unit keeps obtaining fresh ones

3. Revocation chaining

A PID Provider re-checks the WIA and Key Attestation status at least every 24 hours, and revokes the PID if either is revoked

4. Revocation

The Wallet Provider revokes a Wallet Instance, for example after loss or theft, or a WSCD or keystore with a security vulnerability

Outside the EUDI Wallet ecosystem, some Wallet Providers issue wallet attestations with a very short lifespan and no status reference at all, relying on expiry instead of revocation; OpenID4VCI makes the status claim optional. TS3 does not allow that for EUDI Wallets. The WIA already lives less than 24 hours, yet both the WIA and the Key Attestation must carry a status reference that the Wallet Provider maintains for at least 31 days, because PID Providers use it to revoke PIDs long after issuance.

WUA, WIA and KA: which term means what

The terminology changed while the specifications matured. TS3 called the WIA a Wallet App Attestation until version 1.1, and used WUA for what is now the Key Attestation until version 1.5. Older articles and ARF drafts therefore use the terms differently.

TermWhat it coversWho receives it
WUAUmbrella term for the two attestations belowPID Providers and Attestation Providers, during issuance only
WIAThe Wallet Instance, meaning the appThe Authorization Server, in the Pushed Authorization Request and Token Request
KAA WSCD or keystore and the keys it holdsThe Credential Issuer, in the proofs of the Credential Request

Related terms

Frequently asked questions

Is a WUA the same thing as a Wallet Instance Attestation?

No. Since version 1.5 of TS3, WUA is the umbrella term for two attestations: the Wallet Instance Attestation (WIA), which covers the app, and the Key Attestation (KA), which covers the WSCD or keystore holding the keys. Older documents use WUA for what is now called the Key Attestation, which is why the terms are often confused.

Does a verifier ever see the WUA?

No. ARF requirements WUA_07 and WUA_24 allow a Wallet Unit to present a WIA or Key Attestation only to a PID Provider or Attestation Provider during issuance, never to a Relying Party. A verifier checks the credential instead: its signature, its device binding and its revocation status. If the wallet behind a PID is revoked, the PID Provider revokes the PID within its 24-hour check cycle, and the verifier sees that through the PID’s own status.

How long is a WUA valid?

A WIA expires less than 24 hours after the Wallet Provider checked the app’s integrity. A Key Attestation can be valid for longer, at the Wallet Provider’s discretion. Separately, each carries a status maintenance date, client_status.exp or key_storage_status.exp, until which the Wallet Provider keeps the revocation status up to date. The Wallet Unit must always be able to present one whose date is at least 31 days away, and a PID must expire before that date.

What happens if a wallet unit is compromised before its WUA expires?

The Wallet Provider revokes the Wallet Instance on its WIA Status List, or, for a vulnerability in a type of WSCD or keystore, the Status List entry for that storage. A PID Provider checks the WIA and Key Attestation status behind every PID it issued at least once every 24 hours and revokes the PID when either is revoked. Attestation Providers may do the same. Expiry of the WUA itself is not what removes the wallet; the revocation of the credentials issued to it is.

Can one Key Attestation cover more than one key?

Yes. attested_keys can list several public keys from the same WSCD or keystore, which is how batch issuance works: the issuer binds each credential in the batch to a different key, and one Wallet Provider signature covers all of them. When the Key Attestation travels in a jwt proof, the Wallet Unit signs that proof with the first key in the list only.

Sources

  1. TS3: Wallet Unit Attestations used in issuance of PID and Attestations
  2. EUDI Wallet Architecture and Reference Framework
  3. OpenID for Verifiable Credential Issuance 1.0
  4. OpenID4VC High Assurance Interoperability Profile 1.0
  5. OAuth 2.0 Attestation-Based Client Authentication
  6. Token Status List

This page is informational and does not constitute legal advice. For authoritative guidance consult the European Commission and the OpenID Foundation directly.

Talk to us about EUDI Wallet integration