Skip to content

Metadata in credential response#721

Open
c2bo wants to merge 4 commits intomainfrom
421-metadata-in-credentialresponse
Open

Metadata in credential response#721
c2bo wants to merge 4 commits intomainfrom
421-metadata-in-credentialresponse

Conversation

@c2bo
Copy link
Copy Markdown
Member

@c2bo c2bo commented Mar 18, 2026

Closes #421

Not really certain about the only_metadata parameter in the Credential Request.

@c2bo c2bo requested a review from leecam March 18, 2026 07:56
Comment on lines +1261 to +1263
* `jwk`: REQUIRED. Object containing a single public key as a JWK used for encrypting the Credential Response.
* `enc`: REQUIRED. JWE [@!RFC7516] `enc` algorithm [@!RFC7518] for encrypting Credential Responses.
* `zip`: OPTIONAL. JWE [@!RFC7516] `zip` algorithm [@!RFC7518] for compressing Credential Responses prior to encryption. If absent then compression MUST not be used.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it doesn't easily show on the github diff: this is only a fix for indentation (3->2 spaces)

* `interval`: REQUIRED if `transaction_id` is present. Contains a positive number that represents the minimum amount of time in seconds that the Wallet SHOULD wait after receiving the response before sending a new request to the Deferred Credential Endpoint. It MUST NOT be used if the `credentials` parameter is present.
* `notification_id`: OPTIONAL. String identifying one or more Credentials issued in one Credential Response. It MUST be included in the Notification Request as defined in (#notification). It MUST not be used if the `credentials` parameter is not present.
* `metadata`: OPTIONAL. Object that contains additional metadata specific to the issued Credential(s).
* `display`: OPTIONAL. Object that contains additional display information specific to the issued Credential(s). The definitions and contained parameters for this Object are identical to the `display` parameter as defined under the `credential_metadata` parameter in Credential Issuer Metadata (see (#credential-issuer-metadata)). Any values contained here overwrite existing values for display that were contained in the Credential Issuer Metadata.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does "Any values contained here overwrite existing values for display that were contained in the Credential Issuer Metadata." mean? Should you merge the display arrays based on e.g. the locale, or does it overwrite the whole display array? The "Any values contained" indicates to me it overwrites based on values within the array, not the whole array.

Copy link
Copy Markdown
Member Author

@c2bo c2bo Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They way I'd see metadata is in sort of a hierarchy:

  • Issuer metadata: most general form level of metadata
  • Optional format-specific metadata
  • Metadata returned in Credential response

Where Issuer metadata is the default, gets overwritten by format-specific metadata if it exists (only for the values it contains), gets overwritten by credential response (only values that exist in the credential response)

From an implementation perspective:

  • Take everything from the issuer metadata
  • Check for format-specific metadata and for each value found, overwrite your current metadata construct
  • Check Credential Response and for each value found, overwrite your current metadata construct

* `jwk`: REQUIRED. Object containing a single public key as a JWK used for encrypting the Credential Response.
* `enc`: REQUIRED. JWE [@!RFC7516] `enc` algorithm [@!RFC7518] for encrypting Credential Responses.
* `zip`: OPTIONAL. JWE [@!RFC7516] `zip` algorithm [@!RFC7518] for compressing Credential Responses prior to encryption. If absent then compression MUST not be used.
* `only_metadata`: OPTIONAL. Boolean value that if present and set to `true` signals that the Wallet does not expect any credentials in the Credential Response. The Wallet requests only updates to the metadata of previously issued Credentials as identified by the `credential_identifier` or `credential_configuration_id` parameters. If set to `true`, then the `proofs` parameter MUST NOT be present. If the parameter is absent, the value is treated as `false`.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this is reusing the credential endpoint for a completely different purpose. Implementation wise it will have completely different logic I assume? Wouldn't it make more sense to introduce a dedicated endpoint for this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that is why I also said I didn't really confident about that part - I was trying to create an initial proposal that reflects the discussion we had in the WG, which was similar to this

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a bit awkward having credential metadata distributed like this as well.

@c2bo c2bo requested a review from TimoGlastra March 20, 2026 09:33
@c2bo
Copy link
Copy Markdown
Member Author

c2bo commented Mar 20, 2026

Changed it to the variant, where it's just "normal" credential_metadata and added an explanation w/ examples of the mechanism.
Does this work for you @leecam, @TimoGlastra ?

@TimoGlastra
Copy link
Copy Markdown
Member

I like this addition 👍

@c2bo c2bo marked this pull request as ready for review March 20, 2026 16:49
@c2bo
Copy link
Copy Markdown
Member Author

c2bo commented Mar 23, 2026

@Wicpar, could I also ask for a review from you since you provided feedback in the corresponding issue (can't request review directly since you aren't part of the gh organization)?

Copy link
Copy Markdown

@Wicpar Wicpar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot @c2bo for letting me chime in.

In a strict review sense there is a missing way to request the response as a JWT signed by the issuer, attesting its provenance. In the context of PSD2 (banking) legislation, all display elements are the responsibility of the bank, the issuer. This means issuers must ensure that there is a way for wallets to ensure that during all presentations a verification of the persisted data is done before displaying them, in addition to app integrity to ensure the display has happened correctly according to the issuer's definition.


Now in a larger scope does this feature really make sense as it is ?

The original need of the feature is to be able to display card art when receiving the credential, however at that point, one has already the sd-jwt-vc credential ready to decode, and fetch the metadata, and also already has had access to the issuer metadata which also has the credential metadata. It clearly is a nice to have, but does it warrant yet another metadata source ? For that part if it is truly the wish of VCI to provide self contained displayable responses it would make sense to do it like this, but the only_metadata seems overreaching.

Another unrelated need, is the ability to verify, update and securely store potentially heavy metadata objects — common to all credentials of that type — in a high assurance environment where all data must have a known and verified use and provenance.

For that purpose Credential Metadata, as in any metadata that that is common to and lives along the credential type for the length of its life, should be a first class object that belongs to the credential type, and should be able to have a format that can be verified and attributed to the same trust chain as the credential itself. Display is a major part of the consent, and should be securable if required by standards relying on this specification.

I think creating a dedicated endpoint to query metadata like credential_metadata_uri based on the same behavior of the credential endpoint would make a lot more sense, allowing to get clean, signed and/or encrypted credential metadata.

I would even go to deprecating the credential_metadata in the credential_configurations, the issuer metadata request in principle should only advertise data immediately useful to the issuance, and localized display metadata is sure to grow out of proportion way too easily in real world implementations.

In our use-case we do need to be able to get a minimal credential metadata JWT with x5c based on the same trust chain as the credential, and with the sub being the credential type identifier (or a stringified, canonicalized version of it), or another way to have it be tied to the credential in an independently verifiable manner.

@@ -1258,9 +1258,10 @@ A Client makes a Credential Request to the Credential Endpoint by sending the fo
* `credential_configuration_id`: REQUIRED if a `credential_identifiers` parameter was not returned from the Token Response as part of the `authorization_details` parameter. It MUST NOT be used otherwise. String that uniquely identifies one of the keys in the name/value pairs stored in the `credential_configurations_supported` Credential Issuer metadata. The corresponding object in the `credential_configurations_supported` map MUST contain one of the value(s) used in the `scope` parameter in the Authorization Request. When this parameter is used, the `credential_identifier` MUST NOT be present.
* `proofs`: OPTIONAL. Object providing one or more proof of possessions of the cryptographic key material to which the issued Credential instances will be bound to. The `proofs` parameter contains exactly one parameter named as the proof type in (#proof-types), the value set for this parameter is a non-empty array containing parameters as defined by the corresponding proof type.
* `credential_response_encryption`: OPTIONAL. Object containing information for encrypting the Credential Response. If this request element is not present, the corresponding credential response returned is not encrypted.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no mechanism to request an issuer signature of the response equivalent to the jwt response of the issuer metadata.

* `jwk`: REQUIRED. Object containing a single public key as a JWK used for encrypting the Credential Response.
* `enc`: REQUIRED. JWE [@!RFC7516] `enc` algorithm [@!RFC7518] for encrypting Credential Responses.
* `zip`: OPTIONAL. JWE [@!RFC7516] `zip` algorithm [@!RFC7518] for compressing Credential Responses prior to encryption. If absent then compression MUST not be used.
* `only_metadata`: OPTIONAL. Boolean value that if present and set to `true` signals that the Wallet does not expect any credentials in the Credential Response. The Wallet requests only updates to the metadata of previously issued Credentials as identified by the `credential_identifier` or `credential_configuration_id` parameters. If set to `true`, then the `proofs` parameter MUST NOT be present. If the parameter is absent, the value is treated as `false`.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a bit awkward having credential metadata distributed like this as well.

Copy link
Copy Markdown
Member

@fkj fkj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with the previous reviewers that it might be best to define a new general endpoint for this. I think it's important to understand what the use cases for being able to update metadata are.
So far, I've seen these two:

  1. Obtain signed credential metadata (not only for display, but also in general) for compliance with specific laws, e.g. PSD2. (This is @Wicpar's use case as I understand it).
  2. Update credential display name/art/whatever in case the issuer changes branding or similar. We noted this in the NOBID LSP.

"logo": {
"uri": "data:image/png;base64,F00==",
},
"com.emvco.dpc.v1": {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should switch to something generic instead of a real company.

@Wicpar
Copy link
Copy Markdown

Wicpar commented Mar 23, 2026

I agree with the previous reviewers that it might be best to define a new general endpoint for this. I think it's important to understand what the use cases for being able to update metadata are. So far, I've seen these two:

There is also the need to be able to add new locales and update visuals during the lifetime of the credential.
Our use case adds a new transaction_data_types parameter that might need to add new transaction data types supported by the credential when standards evolve. It is too heavy to gracefully be provided in the issuer metadata, we have multiple megabyte payloads for a dozen credentials in our test setup issuer metadata right now.

Co-authored-by: Frederik Krogsdal Jacobsen <fkj@users.noreply.github.com>
Co-authored-by: Christian Bormann <chris.bormann@gmx.de>
@c2bo
Copy link
Copy Markdown
Member Author

c2bo commented Mar 24, 2026

I won't be able to join the DCP call tomorrow morning, but I'd like to have a discussion on the endpoint part in the WG before we are changing towards a new endpoint.

My understanding was that the last time this was discussed, the point of refreshing metadata was briefly brought up and the initial reaction was to allow repeated calls to the credential endpoint with some sort of flag that this request only updates metadata. I don't disagree with moving this to somewhere else, but I'd like to have rough consensus in a WG meeting first. From my perspective, it would make more sense to use something like feature proposed in #300 for the updates though instead of a new endpoint?

@Wicpar
Copy link
Copy Markdown

Wicpar commented Mar 24, 2026

#300 would be useful for the notification part but doesn't really fulfill the need of having a locale-filtered and signed credential metadata object, which hash allows proper identification of the delivered instance (not possible if the credentials are in there with it).

@fkj
Copy link
Copy Markdown
Member

fkj commented Mar 25, 2026

#300 would be useful for the notification part but doesn't really fulfill the need of having a locale-filtered and signed credential metadata object, which hash allows proper identification of the delivered instance (not possible if the credentials are in there with it).

Why would it not be possible to verify signed metadata along with a credential? Because you want the metadata to be a fixed "template" that can be verified statically? I don't understand why you could not sign a second piece of metadata later, e.g. to add a new locale. What exactly do you need to verify for each credential instance?

@c2bo
Copy link
Copy Markdown
Member Author

c2bo commented Mar 25, 2026

#300 would be useful for the notification part but doesn't really fulfill the need of having a locale-filtered and signed credential metadata object, which hash allows proper identification of the delivered instance (not possible if the credentials are in there with it).

Locale-based filtering might be a bit harder, but the issuer could just store the preference sent during the credential issuance flow and keep using that. We could definitely use this channel to convey signed information (JWTs). I am a bit reluctant to introduce a new/dedicated endpoint for this if we would likely move towards the notification based variant mid-/longterm -> That is exactly what I would like to better understand in a WG discussion.

@Wicpar
Copy link
Copy Markdown

Wicpar commented Mar 25, 2026

Why would it not be possible to verify signed metadata along with a credential?

it is possible, the issue comes when needing to verify the hash returned in the kb-jwt that is the signature of the metadata to replay when verifying a transaction after the fact. if it has the credentials along with it, it is not the same as without, it will increase the storage requirements quite a bit as all hashes must have a stored metadata object as it was issued

Because you want the metadata to be a fixed "template" that can be verified statically?

not fixed but it must be verified against the credential and the wallet unit in an independent manner for each different version that was issued.

I don't understand why you could not sign a second piece of metadata later, e.g. to add a new locale.

you could, it's just very inconvenient having hashes multiplied by the number of issuances to store, it becomes quadratic instead of linear. based on user adoption.

What exactly do you need to verify for each credential instance?

PSD2 requires the bank to prove the user has been properly informed and has given consent, it is critical that the presentation can be verifiably replayed after the fact, that every single display detail be provably as it was at that time, with the assumption that the certified wallet indeed respects the spec as the audit certified.
since display is determined by metadata, it must be signed and linked to the proof, like the credential.

the goal is that the kb-jwt + credential + metadata + wallet unit allow the bank to prove the transaction went as defined without user cooperation. for that a dedicated signed credential metadata is necessary, having credentials in there sometimes complicates things significantly.

It is possible to do by calling the metadata endpoint again to get only the metadata, let me think about it a bit more. i jumped the gun a bit when saying it is not possible rather than impractical, sorry about that.

@Wicpar
Copy link
Copy Markdown

Wicpar commented Mar 25, 2026

Locale-based filtering might be a bit harder, but the issuer could just store the preference sent during the credential issuance flow and keep using that.

that is not appropriate as the user preference in the wallet might change at any point in time and should trigger a refresh of the metadata in the relevant locales

We could definitely use this channel to convey signed information (JWTs). I am a bit reluctant to introduce a new/dedicated endpoint for this if we would likely move towards the notification based variant mid-/longterm -> That is exactly what I would like to better understand in a WG discussion.

my worry about a pure notification approach is that it would remove control from the wallet unit on how to refresh the data

@fkj
Copy link
Copy Markdown
Member

fkj commented Mar 25, 2026

it is possible, the issue comes when needing to verify the hash returned in the kb-jwt that is the signature of the metadata to replay when verifying a transaction after the fact. if it has the credentials along with it, it is not the same as without, it will increase the storage requirements quite a bit as all hashes must have a stored metadata object as it was issued

I wonder if this could be solved by returning the metadata in a nested JWT. It could then be verified independently.

you could, it's just very inconvenient having hashes multiplied by the number of issuances to store, it becomes quadratic instead of linear. based on user adoption.

I don't understand this. Would it not be one hash per issued credential metadata instance?

since display is determined by metadata, it must be signed and linked to the proof, like the credential.

Only the metadata that was actually used in the particular presentation needs to be linked to the proof, right? Not every single metadata set present.

On the notification approach, I agree that it is useful but not sufficient. The wallet may also want to initiate fetching new metadata if the user e.g. changes language on their device.

@Wicpar
Copy link
Copy Markdown

Wicpar commented Mar 25, 2026

I wonder if this could be solved by returning the metadata in a nested JWT. It could then be verified independently.

yes, it's just a bit weird to do nested jwts, also how would the request params for the inner jwts look like, it just seems a bit odd.

I don't understand this. Would it not be one hash per issued credential metadata instance?

only if the credential response is not in there, hashing anything else than the signed JWT introcuces too much uncertainty that has to be compensated with extra standard definition. so ideally we would have a clean credential metadata only JWT

Only the metadata that was actually used in the particular presentation needs to be linked to the proof, right? Not every single metadata set present.

Yes if a wallet has a metadata object for FR and one for DE it would just insert the hash of the one used in the KB-JWT. But it cannot divide up a metadata object as the signature must be part of the hash for the proof, so that it can be queried by hash in the issuer database alongside the credential and WUA if there is a case that needs proof without user cooperation.

On the notification approach, I agree that it is useful but not sufficient. The wallet may also want to initiate fetching new metadata if the user e.g. changes language on their device.

👍

@c2bo
Copy link
Copy Markdown
Member Author

c2bo commented Mar 26, 2026

Following the WG discussion today, I removed the update metadata part. The PR now only contains the addition of optional credential_metadata in the Credential Response.

Update to be discussed/solved in another PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add display metadata to the CredentialResponse

5 participants