OpenID4VCI icon indicating copy to clipboard operation
OpenID4VCI copied to clipboard

Credential format profiles: 'claims' definitions a̶r̶e̶ ̶b̶r̶o̶k̶e̶n̶ should be improved

Open danielfett opened this issue 1 year ago • 20 comments

Right now, the definitions (e.g., this) for claims/credentialSubject in the credential format profiles are broken (as pointed out earlier).

At least the following problems exist:

  • There is no way to distinguish between a claim named mandatory and the syntax element mandatory (same for display etc.).
  • There is no way to describe, e.g., the address claim and the address/region sub-claim.
  • The implementer has to parse the structure in order to figure out whether a certain object defines properties of the claim or contains nested claims. While this is possible, it is hard to implement.
  • Handling of arrays of objects is undefined.

This is also related to this issue, both go back to not properly accounting for nested structures.

The problem exists in all three profiles defined in Appendix A.

danielfett avatar Feb 13 '24 21:02 danielfett

Some of the solutions discussed on the last call:

  1. Instead of trying to mimic the structure of the credential, use pointers to the claims that are being described. There are multiple options:
    1. Use JSONPointer (this is what the current draft for SD-JWT VC Type Metadata uses).
    2. Use JSONPath (in my opinion this is not a good option due to complexity, potential security issues and JSONPath being a query language, not a pointer)
    3. Use arrays as pointers, e.g., ["address", "region"]. How array elements can be addressed would need to be defined.
  2. Define that for each element, there is an object with the properties mandatory, display, but also the new property nested which may contain descriptions about nested objects.
  3. At least for SD-JWT VC, an option would be to say that no properties can be defined directly in the issuer metadata, but the vct value can be used to find VC Type Metadata. A new element vctm could contain metadata documents as an array of base64url-encoded documents, similar to the glue documents described in the specification. Integrity protection would need to be figured out.

I personally would prefer 1.3 or 1.1 and provide an option for 3.

danielfett avatar Feb 14 '24 13:02 danielfett

To help clarify the issue:

  • Currently the claims value is a JSON object that mimics the nested structure of the credential
  • The proposal is to make it a map, where nested structures are "flattened", hence the new structure could describe leafs but also parents

We favor Option 1.1, but we observe there might be some obscure use cases not covered by JSON Pointer (description for objects within arrays). Early implementation experience would be handy.

We also favor Option 3 and see 1 as the default fallback option if a credential format does not further specify detailed metadata.

paulbastian avatar Feb 14 '24 13:02 paulbastian

I created a PR on VC Type Metadata to see what complexity solution 1.3 proposed by @bc-pi would bring and I think it is comparable to or easier to implement than the JSONPointer solution considering that the JSONPointer solution would require a workaround for arrays and entail escaping etc..

This is what the metadata could look like: https://vcstuff.github.io/sd-jwt-vc-types/danielfett/fix-claims/draft-fett-oauth-sd-jwt-vc-types.html#section-2

  "claims":[
    {
      "path":["name"],
      "display":{...}
    },
    {
      "path":["address"],
      "display":{...}
    },
    {
      "path":["address", "street_address"],
      "display":{...}
    },
    {
      "path":["degrees", null],
      "display":{...}
    }
  ],

And this is how to parse the path property (Sections 8 and 8.1): https://vcstuff.github.io/sd-jwt-vc-types/danielfett/fix-claims/draft-fett-oauth-sd-jwt-vc-types.html#section-8

(PR in SD-JWT VC Type Metadata)

danielfett avatar Feb 14 '24 14:02 danielfett

I don't think we currently use 'null' JSON values anywhere in the VCI spec. I would argue that JSON nulls are generally problematic and should be avoided as many JSON libraries (at least by default) consider 'null' to be equivalent to 'not present'.

Perhaps we could follow the precedent set in the SD JWT spec with _sd_alg and so on and use something like _oid4vc_all_array_entries? Other possibilities might be -1, true, or {}.

jogu avatar Feb 14 '24 16:02 jogu

Option 1.4: rename mandatory and display to values with _mandatory and _display (addresses only parts of the problems)

paulbastian avatar Feb 14 '24 16:02 paulbastian

For what it's worth, https://www.rfc-editor.org/rfc/rfc7592.html#section-2.2 treats null metadata values as a request to delete the metadata parameter - not as a literal value.

For similar reasons, the OpenID Federation spec states that null metadata parameter values MUST not be used.

This is rooted in Java and Python behaviors where "getting" a value from a structure returns null for values that are not present, rather than throwing an exception.

selfissued avatar Feb 14 '24 16:02 selfissued

A null value here in the context of @danielfett's 1.3 is an array element, which is a different usage than the reasons we've (sometimes) avoided it in specs. So I kinda think it's fine here. But if we really feel that using null needs to be avoided, I'd argue that we still want to stay away from special names like "_oid4vc_all_array_entries" or similar. I think using -1or any non-positive number would be the way to go.

bc-pi avatar Feb 14 '24 16:02 bc-pi

I have a really hard time imagining how null could be a problem in this specific context, but -1 would be the second best option.

danielfett avatar Feb 14 '24 17:02 danielfett

Some of the solutions discussed on the last call:

  1. Instead of trying to mimic the structure of the credential, use pointers to the claims that are being described. There are multiple options:

    1. Use JSONPointer (this is what the current draft for SD-JWT VC Type Metadata uses).
    2. Use JSONPath (in my opinion this is not a good option due to complexity, potential security issues and JSONPath being a query language, not a pointer)
    3. Use arrays as pointers, e.g., ["address", "region"]. How array elements can be addressed would need to be defined.
  2. Define that for each element, there is an object with the properties mandatory, display, but also the new property nested which may contain descriptions about nested objects.

  3. At least for SD-JWT VC, an option would be to say that no properties can be defined directly in the issuer metadata, but the vct value can be used to find VC Type Metadata. A new element vctm could contain metadata documents as an array of base64url-encoded documents, similar to the glue documents described in the specification. Integrity protection would need to be figured out.

I personally would prefer 1.3 or 1.1 and provide an option for 3.

I would prefer option 2, introduce a nested property. It is the cleanest option and most intuitive option imo.

awoie avatar Feb 15 '24 07:02 awoie

Agree it is a problem that should be addressed and support the proposed option 1.3 (aka 1.iii) "Use arrays as pointers." 

It also seems worthwhile to consider allowing for something along the lines of option 3.  And have SD-JWT VC Type Metadata also use an arrays as pointers approach.

bc-pi avatar Feb 15 '24 14:02 bc-pi

To help clarify the issue:

  • Currently the claims value is a JSON object that mimics the nested structure of the credential
  • The proposal is to make it a map, where nested structures are "flattened", hence the new structure could describe leafs but also parents

We favor Option 1.1, but we observe there might be some obscure use cases not covered by JSON Pointer (description for objects within arrays). Early implementation experience would be handy.

We also favor Option 3 and see 1 as the default fallback option if a credential format does not further specify detailed metadata.

Perhaps I am misunderstanding JSON Pointer, but from my understanding you can reference objects within an array?

Wouldn't this work?

{
  "data": [
    {
      "some": "value"
    },
    {
      "more": 42
    }
  ]
}

JSONPointer("/data/0/some") == "value"

I don't fully understand or see the benefit of going with the Option 1.3 over 1.1 but I might very well be missing something.

c2bo avatar Feb 15 '24 14:02 c2bo

The problem is that you might want to say "every element in that array". So "/data/*/some" (which is not valid JSONPointer). More like a query language... So maybe this is an appropriate use of JSONPath (but that is still too complex and still potentially insecure).

danielfett avatar Feb 15 '24 14:02 danielfett

My preference would be

  1. Prefix parameters to decrease collisions (e.g. __display) (option 2(-2))
  2. Use nested attribute (option 2(-1))

It keeps things simple, closely linked to the attribute and straightforward to implement, improving adoption.

javereec avatar Feb 15 '24 16:02 javereec

Consensus in the call was to go ahead with solution 1.3 following the SD-JWT VC Type Metadata mechanism (and then collecting initial implementer's feedback before proceeding).

If everyone could please review this section in VC Type Metadata and provide feedback before I create the PR for VCI on Monday, that would be very helpful: https://vcstuff.github.io/sd-jwt-vc-types/danielfett/fix-claims/draft-fett-oauth-sd-jwt-vc-types.html#name-claim-metadata

PR for commenting here: https://github.com/vcstuff/sd-jwt-vc-types/pull/5

danielfett avatar Feb 15 '24 17:02 danielfett

If everyone could please review this section in VC Type Metadata and provide feedback before I create the PR for VCI on Monday, that would be very helpful: https://vcstuff.github.io/sd-jwt-vc-types/danielfett/fix-claims/draft-fett-oauth-sd-jwt-vc-types.html#name-claim-metadata

I presume we'll carry across the 'mandatory' and 'value_types' fields that are in the current VCI draft?

I'm not sure if it's clear whether or not the proposal is to add the 'sd' and 'verification' fields that are defined in the above link to VCI?

(And as discussed in the call, this change would mean we can remove the 'order' parameter that's in the current spec.)

jogu avatar Feb 15 '24 17:02 jogu

We have been working on a similar problem in the context of a format-specific query syntax. Perhaps that work can help inform thinking and conversation around describing claim structures for different formats (IETF SD-JWT VC, W3C VCDM 2.0, and ISO mdocs) in JSON and vice versa. Here's a the link:

https://docs.google.com/document/d/10JT--pXWsfwC4QVu3XJpXGwcO08M6tnpkZ4PKdtCEWo

awoie avatar Feb 15 '24 19:02 awoie

If everyone could please review this section in VC Type Metadata and provide feedback before I create the PR for VCI on Monday, that would be very helpful: https://vcstuff.github.io/sd-jwt-vc-types/danielfett/fix-claims/draft-fett-oauth-sd-jwt-vc-types.html#name-claim-metadata

I presume we'll carry across the 'mandatory' and 'value_types' fields that are in the current VCI draft?

yes

I'm not sure if it's clear whether or not the proposal is to add the 'sd' and 'verification' fields that are defined in the above link to VCI?

I think we wouldn't use those.

(And as discussed in the call, this change would mean we can remove the 'order' parameter that's in the current spec.)

Which has its own problems.

danielfett avatar Feb 15 '24 20:02 danielfett

we discussed this internally with Microsoft engineers. We do not currently have use-cases with the claims that have nested structure and array-based solution is too big of a breaking change. So our preference is actually approach 2 with defining the new property nested which may contain descriptions about nested objects.

As a compromise, my suggestion would be fixing the text that becomes ID-1 with nested approach. and than after ID-1, incorporating the array approach.

Sakurann avatar Feb 22 '24 23:02 Sakurann

suggesting @jogu to do a non-normative PR explaining what does not work in the current structure, before PR #278 gets merged. ideally before March 18th to get into ID-1

Sakurann avatar Feb 27 '24 20:02 Sakurann

@danielfett can you please change the issue name from "is broken" to something like "needs improvement"? Implementation feedback showed that the current structure works for majority of the current use-cases, so broken feels too strong and potentially misleading. thank you!

Sakurann avatar Mar 01 '24 09:03 Sakurann