-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adapt PID rulebook to latest SD-JWT VC #160
base: main
Are you sure you want to change the base?
Adapt PID rulebook to latest SD-JWT VC #160
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
only editorials by my side, some further readings makes me more sensible from the reader perspective. I consider this approved even If I'm requesting these trivial editorials
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think I have any power to approve here but looks good to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO, this looks good and fills an important gap in the specification. I really appreciate this addition.
The proposed claim set does not seem to include a claim that would specify the namespace/credential type Consider the following presentation definition with which an RP requests {
"id": "foobar",
"vp_formats": {
"vc+sd-jwt": {
"sd-jwt_alg_values": [
"ES256"
],
"kb-jwt_alg_values": [
"ES256"
]
}
},
"input_descriptors": [
{
"id": "given_name",
"constraints": {
"fields": [
{
"path": [
"$.credential_type"
],
"filter": {
"const": "eu.europa.ec.eudi.pid.1"
}
},
{
"path": [
"$.given_name"
],
"filter": {
"type": "string"
}
}
]
}
}
]
} Also, the claim set does not include
If the RPs instead selected using {
"id": "foobar",
"vp_formats": {
"vc+sd-jwt": {
"sd-jwt_alg_values": [
"ES256"
],
"kb-jwt_alg_values": [
"ES256"
]
}
},
"input_descriptors": [
{
"id": "given_name",
"constraints": {
"fields": [
{
"path": [
"$.credential_type"
],
"filter": {
"const": "eu.europa.ec.eudi.pid.1"
}
},
{
"path": [
"$.issuing_country"
],
"filter": {
"const": "DE"
}
},
{
"path": [
"$.given_name"
],
"filter": {
"type": "string"
}
}
]
}
}
]
} |
Co-authored-by: Giuseppe De Marco <[email protected]>
Co-authored-by: Christian Bormann <[email protected]>
Thank you very much @danielfett for your replies to my comments and for the changes you made!
So essentially
The wallet and the RP would not be able to rely on existing JSON Schema implementations because Such custom mapping logic could require that each party, that evaluates presentation definitions¹, would need to maintain or download from somewhere a list of An alternative Either way custom mapping logic of ¹ The evaluating party could be a wallet (in order to respond to the RP's request) or an RP (in order to validate that what they received from the wallet is what they requested). ² Downloading chains of metadata documents also raises the question how the authenticity and authoritativeness of these metadata documents are established. Digest checks at each step of the way? |
We will likely have custom attributes in similar credentials - even in the PID if i understand correctly. Imho, it is important to convey that information clearly - what type of PID the presented credential exactly is. Given that mental model, some kind of type hierarchy/derivation seems to be necessary. I do believe it would be dangerous to ignore that aspect and it might also limit the usability of the technology outside of the initial use-cases/scope. That being said, I also agree with you that we need to make sure this is still reasonable easy to implement.
If the vct chain is critical to the functionality of the credential (as it would be in the case of the PID), it could be included in the presentation that is transmitted. The sd-jwt-vc draft proposes to use the unprotected header to optionally transport that kind of information (https://drafts.oauth.net/oauth-sd-jwt-vc/draft-ietf-oauth-sd-jwt-vc.html#name-from-type-metadata-glue-doc). That way for credentials like the PID, the wallet could directly convey that information.
That would be my current understanding of the mechanism and the proposed integrity checks. |
I understand your points and I do agree that there needs to be separate issuer and member state specific metadata documents that describe the custom nuances of each issuer's PID. I am not arguing against the
Including the metadata documents in the presentation sounds like a reasonable solution. It would solve the performance and caching issues I mentioned. |
Would it be fine to add this also into the unsigned part? Basically something like a credential type "root" that can easily be processed and later on checked for correctness. That way we could initially easily check if the answer is of the expected type (e.g., EU PID) and then properly do the integrity checks + validate if that PID type is really part of the vct chain. |
Why in the unsigned part specifically? I was thinking |
To @danielfett's point, a similar approach to ISO mdocs could be defined for the ISO TS 18013-7 (latest draft) defines a profile of presentation exchanges that describes how to use presentation definition objects with ISO mdocs. Because ISO mdocs are CBOR-based, JSONPath makes no sense. For that reason, a profile definition was needed. For example, the ISO mdoc doctype has to match the Example:
IMO, another thing I wanted to add is that it is reasonable to assume the wallet itself will always have the full type metadata chain locally cached. I assume the same for relying parties. I don't see a caching issue there. |
It is reasonable to assume that the wallet has the full metadata chain locally cached. However, it's different for the RP. There are at least 27 PID providers. This could mean that an RP has to cache 27 metadata chains + however many active versions there are of each chain. It's not huge but it's not nothing either. |
That would only work for 1 level of type dependency - if you have 3 or more levels, you wouldn't know what to put in there. Let me try to construct a concrete example - let's assume that we have something like this for credential types: A Relying Party could request the EU PID or the worldwide PID and depending on the request, you would expect different values in
Agreed, especially for cases where we expect a somewhat large amount of different Issuers with different credential types but a common schema, the wallet should IMHO be able to optionally provide this information. |
Hmm. I did not know we needed to consider worldwide PIDs. I thought EU PID was the root namespace. Worldwide PID namespace certainly makes Just as an idea, I have not yet thought this through: {
"credential_type": [
"<worldwide PID identifier>",
"eu.europa.ec.eudi.pid.1", // EU PID identifier
"<German PID identifier>"
]
} An array of hierachical identifiers would make the PID selectable using any of the identifiers in the array. For that we can use JSON Schema's {
...
"input_descriptors": [
{
"id": "given_name",
"constraints": {
"fields": [
{
"path": [
"$.credential_type"
],
"filter": {
"type": "array",
"contains": {
"const": "eu.europa.ec.eudi.pid.1"
}
}
},
{
"path": [
"$.given_name"
],
"filter": {
"type": "string"
}
}
]
}
}
]
} |
I don't think we need to consider worldwide PIDs specifically for the time being, but we should try to design a system (if possible without too much added complexity) that can deal with those kinds of problems. A big part of the adoption of this technology will IMHO be the applicability to other (especially unregulated) use-cases and this kind of type hierarchy will be present in a lot of them. Providing something like the array of types could definitely work, but I am still not sure that adding this as redundant signed data is the path to go. I would personally prefer to solve this in the query language & credential format specific processing. |
Dear all. |
We appreciate your proposal and are in agreement with it in principle. However, we would like to receive feedback from the eIDAS expert group regarding two specific consequences of your proposal: Increased code complexity: Namespace and Flexibility Concerns: Before we proceed to merge the pull request, we would like to receive feedback from experts of other member states in the expert group. This will ensure a comprehensive evaluation and consensus on the proposed changes. We look forward to discussing these points further to ensure the robustness of the solution. |
There is no requirement to use IANA for other attestation types. Attribute names can be defined per attestation type domain by the domain itself, e.g., using collision-resistant identifiers, e.g., |
Continuing the previous discussion about I proposed that in addition to {
"credential_type": [
"eu.europa.ec.eudi.pid.1", // EU PID identifier
"<German PID identifier>"
]
} I understood that @danielfett and @c2bo propose a solution where mapping of |
Any news so far? |
I fixed the merge conflicts this PR collected since I last touched it. In the meantime, there has also been progress on the query language in OpenID4VP. Here are the format-specific considerations that describe the |
|
||
Data element identifiers not listed in Table 3 are used as defined above. | ||
|
||
| Data Element Identifier | Claim Name | Note | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to have next to each register claim a reference ?
For instance,
Attribute identifier | Claim Name | Note | Reference |
---|---|---|---|
family_name | family_name | OpenID Connect Core 1.0, Section 5.1 | |
given_name | given_name | OpenID Connect Core 1.0, Section 5.1 | |
birth_date | birthdate | OpenID Connect Core 1.0, Section 5.1 | |
age_over_18 | age_equal_or_over.18 | The 18 property name is a string. |
PID rulebook |
age_over_NN | age_equal_or_over.NN | The NN property name is a string. | PID rulebook |
age_in_years | age_in_years | PID rulebook | |
age_birth_year | age_birth_year | PID rulebook | |
family_name_birth | birth_family_name | OpenID Connect for Identity Assurance Claims Registration 1.0, Section 4 | |
given_name_birth | birth_given_name | OpenID Connect for Identity Assurance Claims Registration 1.0, Section 4 | |
birth_place | place_of_birth.locality | OpenID Connect for Identity Assurance Claims Registration 1.0, Section 4 | |
birth_country | place_of_birth.country | OpenID Connect for Identity Assurance Claims Registration 1.0, Section 4 | |
birth_state | place_of_birth.region | OpenID Connect for Identity Assurance Claims Registration 1.0, Section 4 | |
birth_city | place_of_birth.locality | OpenID Connect for Identity Assurance Claims Registration 1.0, Section 4 | |
resident_address | address.formatted | OpenID Connect for Identity Assurance Claims Registration 1.0, Section 4 | |
resident_country | address.country | OpenID Connect for Identity Assurance Claims Registration 1.0, Section 4 | |
resident_state | address.region | OpenID Connect for Identity Assurance Claims Registration 1.0, Section 4 | |
resident_city | address.locality | OpenID Connect for Identity Assurance Claims Registration 1.0, Section 4 | |
resident_postal_code | address.postal_code | OpenID Connect for Identity Assurance Claims Registration 1.0, Section 4 | |
resident_street | address.street_address | OpenID Connect for Identity Assurance Claims Registration 1.0, Section 4 | |
resident_house_number | address.house_number | OpenID Connect for Identity Assurance Claims Registration 1.0, Section 4 | |
gender | gender | Data type mismatch - JWT claims use male , female and custom text values.* |
OpenID Connect for Identity Assurance Claims Registration 1.0, Section 4 |
nationality | nationalities | Defined as an array, here containing only one entry. | OpenID Connect for Identity Assurance Claims Registration 1.0, Section 4 |
issuance_date | iat | RFC7519 | |
expiry_date | exp | RFC7519 | |
issuing_authority | issuing_authority | PID rulebook | |
document_number | document_number | PID rulebook | |
administrative_number | administrative_number | PID rulebook | |
issuing_country | issuing_country | PID rulebook | |
issuing_jurisdiction | issuing_jurisdiction | PID rulebook |
"issuing_authority": "DE", | ||
"issuing_country": "DE" | ||
} | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be helpful to the reader to have an example of the JWT claim set of the SD-JWT.
Especially to demonstrate the requirement to have selectively disclosable the attributes of claims like age_equal_or_over
, address
etc.
For instance,
{
"vct": "https://memberstate.example/credential/pid",
"vct#integrity": "sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM",
"_sd": [
"4WIgurnNMUzWOG3sbmmVbhcZScJ2coGwSbmcZrPtumA",
"XQMnqxzAbDMg-H0XQvS99IrW7Mpl4D2zTBRyfmQgTKY",
"YtWxyVoyG-gFNACWviWRXHsl1X4RtYSjB22Mspc4Zy0",
"cACZqNooaasU06tJB4wbqd8a2BWrx2h-nh-QnrE4CGM",
"fCJZUjADw2ZYmtWHy_AM-rOf9I_YnxUczsYhwpkbpaI",
"gaxq0QkII8P_QmhGSSaiCPJRuoPIFiEYhp0ZCUP_HAk",
"qgberZ_GO_M0luD--6ICnKoJoNsGniGMl5bP0mt1KS8",
"v_ufEM5Ozoub5HdXM6QzPoJefxzn6-9Jp-KYIvp5K78",
"wkt-dqQ0QJi3Mbw9_1v4PSl5Tyluctzy0BPbPasX4lI"
],
"age_equal_or_over": {
"_sd": [
"51F7iAPg_JZLYQOZzmInfVb7Dm4A7ItKjf0DzLaFuRg",
"8ehSQCxHC90lQQvwPqJmlsE3aBsTLXfSFdABhG1r4oY",
"XziOO_oHFXgJO6HYVClDMQorsAOMU9P-AUqB4Ab8J6o",
"kvFx5InkYZJJ72tEwsG27fi3jBGoatsZiVd3vA0b7Ak",
"lQYi2wOoTefTc4rK-9Cq2mKW2Onwulk-e08f2r7SqDE",
"vh3-Wnego_RenqKkZ_Alnteo8TVU_9Z-IyfNzaRNoOg"
]
},
"address": {
"_sd": [
"Fc909lFNobvjDRO4JCkkcRS24PtkAxzRarxPVJ4GorY",
"I-da3bVCY1n6Koam7K2NMjyvTo8plzfvGeytvt7OgeM",
"NzSDBxiSqMaFdIH92g281e47aBB3c_AXEOmVRucd3zw",
"dpha7BGCPK1ZQyL9rFiNuEdvvSnkpGYSXfbskeK9T-I",
"jqepCG5AgZE2zoDo_MjEZbzToSMnwZ90Oo5_3bMuYEE"
]
},
"place_of_birth": {
"_sd": [
"RZbCkkoc5yDveqfCZYxJqJbIKySbvGzfVfY_vwi2Srs",
"WqbCLRC31iMI67-sdGkdyd5-e7Y-2SdDM-NOrZQR3O0",
"pEtPxpWa4yYISJR9Po74E6b0Ij_qsVxH3IPv4xzrFNo"
]
},
"cnf": {
"jwk": {
"kty": "EC",
"crv": "P-256",
"x": "52aDI_ur05n1f_p3jiYGUU82oKZr3m4LsAErM536crQ",
"y": "ckhZ-KQ5aXNL91R8Eufg1aOf8Z5pZJnIvuCzNGfdnzo"
}
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might be nice, but can we please merge this PR as a starting point, and then do an additional PR to add examples. etc.?
This is starting to cause interoperability issues in international LSP testing. Merging this would really help. Thank you. |
| `gender` | `gender` | Note: Data type mismatch - JWT claims use `male`, `female` and custom text values.* | | ||
| `nationality` | `nationalities` | Note: Defined as an array, here containing only one entry.| | ||
| `issuance_date` | `iat` | | | ||
| `expiry_date` | `exp` | | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issuance_date
and iat
are not necessarily the same thing. The same applies to expiry_date
and exp
. Compare this to the mdoc PID. The mdoc PID issuance_date
and expiry_date
attributes are separate from the MSO signed
and validUntil
timestamps.
issuance_date
and expiry_date
likely express the administrative validity of the PID while iat
and exp
express the validity of the JWT which might be considerably shorter than the administrative validity.
The current description of the usage of SD-JWT in the PID rulebook is not sufficient to result in PID attestations that are compatible to existing conventions and standards like JWTs and SD-JWT VC in particular. The changes proposed here adapt the PID rulebook to be compatible with SD-JWT VC and to work in the direction proposed in SD-JWT VC DM.
The goal is also to make the best usage of SD-JWT VC Type Metadata, even though not all parts of that have made it into SD-JWT VC yet. This allows for automated discovery and processing of type metadata, like schemas (e.g., for relying parties) and rendering information