Skip to main content

Wallet and Key Attestation

During issuance, EUDIPLO can check two statements signed by the wallet provider: a wallet attestation, which proves that the wallet app is a genuine instance of a trusted wallet, and a key attestation, which describes how the holder keys are protected. Both are trusted through wallet-provider trust lists.

Wallet attestationKey attestation
ProvesThe wallet, as OAuth client, is an app of a trusted wallet providerThe holder keys and their storage and user-authentication level
Checked atPAR and token endpoints of EUDIPLO-managed authorization servers (built-in, chained, oid4vp)Credential endpoint, including deferred issuance
Required bywalletAttestationRequired of the authorization server, else of the issuance configurationProof types allowed by the credential configuration (config.proofTypesSupported)
Trusted throughwalletProviderTrustLists of the authorization server, else of the issuance configurationwalletProviderTrustLists of the issuance configuration only

1. Provide wallet-provider trust lists​

Wallet-provider trust lists are LoTE JWTs whose entities offer the service types http://uri.etsi.org/19602/SvcType/WalletSolution, .../WalletSolution/Issuance or .../WalletSolution/Revocation. Reference them like any trust list:

  • External list, for example the wallet provider list published for your ecosystem: { "url": "https://...", "verifierX509Der": "MIIB..." } (or verifierKey). Obtain the verification certificate through a trusted channel; it authenticates the list, not the providers in it.
  • Managed list of this tenant: { "trustListId": "wallet-providers" }. Create it under Trust Lists and set Provider type → Wallet provider on each entity ("providerType": "wallet-provider"). EUDIPLO then publishes WalletSolution/Issuance and WalletSolution/Revocation services; a list with only wallet-provider entities uses the wallet-provider scheme of ETSI TS 119 602 Annex E. If wallet and key attestations are signed by different provider CAs, list both.

Put the lists into the issuance configuration so that both checks can use them:

{
"walletProviderTrustLists": [{ "trustListId": "wallet-providers" }],
"authorizationServers": [
{ "type": "built-in", "id": "issuer-built-in", "walletAttestationRequired": true }
]
}

Merge these fields into your issuance configuration (Issuance Configuration). A presented wallet or key attestation without a configured trust list is always rejected; plain holder proofs without key attestation need no trust list.

2. Require wallet attestation​

When wallet attestation is used, the wallet sends two headers to the PAR and token endpoints, following OpenID4VCI Appendix E:

  • OAuth-Client-Attestation: the attestation JWT signed by the wallet provider, with its certificate chain in x5c and the wallet instance key in cnf,
  • OAuth-Client-Attestation-PoP: a proof of possession signed with that instance key.

EUDIPLO verifies both signatures, builds a certificate path from x5c to a wallet provider in the trust lists and, if the attestation has a status claim, rejects revoked or suspended attestations. If the status list cannot be fetched, the error is logged and the attestation is accepted.

Each EUDIPLO-managed authorization server resolves two settings independently:

SettingValue used
walletAttestationRequiredThe authorization server's value, else the issuance configuration's, else false
walletProviderTrustListsThe authorization server's list, else the issuance configuration's, else none

With true, requests without attestation are rejected; with false, a wallet may omit it, but an attestation it sends must still be valid and trusted. An empty list on the authorization server disables inheritance and rejects every presented attestation. The authorization server metadata advertises attest_jwt_client_auth only when attestation is required. In the Web Client, the authorization server settings offer Use issuer default and Use shared wallet provider trust lists. An external authorization server checks wallets according to its own configuration.

3. Require key attestation​

Key attestations are configured per credential type, in the credential configuration's config:

{
"config": {
"proofTypesSupported": ["attestation"],
"keyAttestationsRequired": {
"key_storage": ["iso_18045_high"],
"user_authentication": ["iso_18045_high"]
}
}
}
  • proofTypesSupported limits the accepted proof types, jwt and attestation (default: both). A proof of another type is rejected with invalid_proof.

  • keyAttestationsRequired is published as key_attestations_required for every supported proof type in the issuer metadata and enforced at the credential endpoint:

    • Every proof must carry a key attestation: an attestation proof or a jwt proof with key_attestation.
    • Every key the proof proves must be listed in the attestation's attested_keys.
    • For a non-empty key_storage or user_authentication list, the attestation must state at least one of the listed values in the claim of the same name.

    An empty object requires a key attestation without level constraints; empty lists add no constraint and are not published. A proof that fails is rejected with invalid_proof. Without keyAttestationsRequired, a key attestation is optional.

Wallets send key attestations in two ways:

  • attestation proof (proofs.attestation): the key attestation JWT itself. EUDIPLO issues one credential per key in its attested_keys, at most the issuance batchSize.
  • jwt proof with key_attestation header: a holder proof whose signing key must be one of the attested keys.

Every presented key attestation must be signed by a wallet provider in the issuance-level walletProviderTrustLists, whether it is required or not; lists on an authorization server are not used for keys.

Troubleshooting​

SymptomCause and fix
Wallet attestation is required but not providedThe wallet sends no attestation headers. Use a wallet that supports wallet attestation, or set walletAttestationRequired: false.
No wallet provider trust lists configured ...Neither the authorization server nor the issuance configuration has walletProviderTrustLists (for key attestations: the issuance configuration).
... signer is not trusted by configured wallet provider trust listsThe provider's certificate is not in the lists, or listed without a WalletSolution service type.
The credential configuration requires a key attestation ...The wallet sent a jwt proof without key_attestation. Use a wallet that sends key attestations, or remove keyAttestationsRequired.
The key attestation does not state an accepted key_storage value ... (or user_authentication)The attested level is not in the configured list. Add the level your wallets attest, if it meets your requirements.
The proof contains a key that is not listed in attested_keys ...The jwt proof is signed with a key the attestation does not cover.
Wallet attestation verification failed: ... or Attestation proof x5c chain could not be validatedOften a trust list problem: the list cannot be fetched or its signature does not match verifierX509Der/verifierKey. Check the server log for the reason.