Skip to content

CredentialMetadata drops credential_metadata.claims[], so wallets cannot show the issuer's published claim names #1945

Description

@mc1100

Version: observed on 0.99.0; re-checked against main @ 145e9e1a — unchanged.

What happens

OpenID4VCI lets an issuer publish a display name per claim, localized. Here is the real metadata from the EU reference issuer, configuration eu.europa.ec.eudi.pid_vc_sd_jwtcredential_metadata.claims is an array of 31 entries in this configuration alone:

"credential_metadata": {
  "display": [ /**/ ],
  "claims": [
    { "path": ["family_name"], "mandatory": true,
      "display": [ { "name": "Family Name(s)", "locale": "en" } ] },
    { "path": ["given_name"],  "mandatory": true,
      "display": [ { "name": "Given Name(s)",  "locale": "en" } ] }
    // … 29 more
  ]
}

multipaz reads that same object for the credential-level display and drops claims on the floor:

credentials[id] = CredentialMetadata(
display = extractDisplay(
element = config.objOrNull("credential_metadata") ?: config,
httpClient = httpClient,
clientPreferences = clientPreferences
),
format = format,
keyBindingType = keyProofType,
maxBatchSize = maxBatchSize
)
}

CredentialMetadata has nowhere to put them — it carries a credential-level Display and nothing else:

data class CredentialMetadata(
/** Credential name and visual representation of that credential in the wallet. */
val display: Display,
/** Format of this credential */
val format: CredentialFormat,
/** Determines how the key to which the credential is bound should be provided to the issuer */
val keyBindingType: KeyBindingType,
/** Maximum number of credentials that can be requested in a single request */
val maxBatchSize: Int
) {

Why it matters

A wallet that relies on multipaz for issuance metadata has no source for claim names other than a local DocumentTypeRepository. For any credential type not baked into the app — which is the whole point of a wallet that can be pointed at a new issuer — the user is shown raw identifiers like family_name and birth_date, in English, regardless of the locale the issuer published. The issuer sent the right names; they were parsed and discarded.

Suggested fix

Carry the per-claim display through: a claims: List<ClaimMetadata> on CredentialMetadata, where each entry holds the claim path and its display entries, populated in IssuerConfiguration from credential_metadata.claims[].

One design note from implementing this ourselves: we found it necessary to keep all published locales rather than resolving to one at parse time, so the language can be chosen when the screen is drawn rather than frozen at issuance. extractDisplay currently resolves against clientPreferences.locales during parsing (and carries a TODO about exact-match-only being too restrictive), which would freeze claim names to the locale in force at issuance time.

Related

  • Unable to retrieve all credential_metadata display attributes #1784 (closed) reported the same class of loss one level up — description, background_color, background_image, text_color missing from Display — and those attributes are now on Display. This is the remaining half of that metadata gap: the credential-level display was completed, the per-claim display is still discarded.

Workaround we ship

Our compatibility layer re-reads the raw issuer metadata JSON and lifts credential_metadata.claims[].display[] out itself, keyed by doctype/vct, storing every locale alongside the document.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    Inbox

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions