Open awoie opened 4 months ago
Is this limited to DC API profile? I'm asking since underneath there most be a OID4VP for mdoc profile. Would this then be done in the DCP WG, too?
Is this limited to DC API profile? I'm asking since underneath there most be a OID4VP for mdoc profile. Would this then be done in the DCP WG, too?
What is required for the ISO mdoc-specific part is really just defining the SessionTranscript
which is the "thing" that gets signed by the VP. This is essentially just defining where to put origin
and other params in the SessionScript
. This handover has to be done for SD-JWT VC and other credential formats as well.
what about the ISO specific identifiers and so, just what constitutes a profiles.
Is this limited to DC API profile? I'm asking since underneath there most be a OID4VP for mdoc profile. Would this then be done in the DCP WG, too?
What is required for the ISO mdoc-specific part is really just defining the
SessionTranscript
which is the "thing" that gets signed by the VP. This is essentially just defining where to putorigin
and other params in theSessionScript
. This handover has to be done for SD-JWT VC and other credential formats as well.
It is a DCP WG decision if the requirements from the ISO WG can be included in the OID4VP DI API Annex already.
Hereby a proposal for a profile that addresses the request from ISO SC17/WG10. It defines all details necessary to have a successful interaction when the wallet and relying party implement the mandatory requirements of this profile. The profile has been designed to implement the requirements applicable to the openid4vp protocol for the digital credentials API as defined in annex a.
One of the open tasks before making a PR is to make sure it's WebIDL compatible. Making it WebIDL compatible could require making changes to the proposal.
Request object This contains the Authorization Request dictionary.
It MUST have the following two elements: vp_query_info (string) response_encryption (string)
It MAY have the following element verifier_authentications (array/sequence)
These elements have the following definitions: vp_query_info This is a new parameter for the Authorization Request. This element contains the new query language. To support request signing, the value of this element MUST be BASE64URL(UTF8(vp_query)) where vp_query is the structure as defined in #vp_query.
response_encryption This is a new parameter for the Authorization Request. This element contains the elements needed for response encryption. To support RP authentication, the value of this element MUST be BASE64URL(UTF8(response_encryption_parameters)). Where response_encryption_parameters is defined below.
response_encryption_paramaters This dictionary MUST contain the type, nonce and jwk parameters and MAY contain the verifier_authentications parameter.
type is an element that defines the response encryption type, for this profile the value MUST be “mdoc_profile_encryption_1”. nonce is the nonce as defined in section 5. jwk contains the response encryption key of the verifier, the value MUST be a jwk as defined in RFC 7517.
verifier_authentications: This is an array of verifier_authentication. If present, it MUST contain at least one verifier_authentication.
verifier_authentication: This is an array that MUST contain two elements, type and value. type is an element that defines the response encryption type. value is an element the type dependent element that contains the verifier authentication information.
An example for verifier authentication are: type: “verifier_authentication_example” value: jws with detached signed data being the response_encryption_value
type: “request_signature_example” value: array of two elements. First element is base64url(utf8(client_info)), where client_info must contain expected_origins as defined in [xx] and MAY contain client_id and client_id_scheme. Second element is a jws with the detached data being the concatenation of the first array element, vp_query_info and response_encryption values.
Response
The response structure is a dictionary that MUST have the following two elements:
type (string) is an element that defines the response encryption type value is a type dependent element that contains the encrypted response
For this profile, type MUST be “mdoc_profile_encryption_1”. For this profile, value MUST be a structure with two elements:
jwk contains the response encryption key of the verifier, the value MUST be a jwk as defined in RFC 7517 encrypted_data this contains the authorization response containing the encrypted authorization response as BASE64URL(UTF8(authorization_response)). The authorization_response MUST contain a single element vp_token. The vp_token contains the base64url encoded DeviceResponse as defined in 18013-5.
Note 1: It is still to be defined how the RP knows how to decode the elements in the vp_token array since that may be part of the update on the query language. Currently, this is implicit through the use of the profile parameter. Note 2: The presentation_submission parameter is absent as that's part of the update to the query language in a different issue.
The value of the encrypted_response shall be calculated by taking the CBOR encoded DeviceResponse and encrypting it with HPKE (RFC 9180) with the following parameters:
Mode: Base KEM: DHKEM_P256 KDF: HKDF_SHA256 AEAD: AES_128_GCM
The keys used are the Verifier and RP response encryption keys in the respective jwk elements. The HPKE info parameter is the cbor encoded SessionTranscript. The SessionTranscript MUST have the following structure:
SessionTranscript = [
null,
null,
[
"browser_handover_v1",
response_encryption, ; the string from the request
Origin ; this is a tstr containing the domain of the website making the request
]
]
@martijnharing thanks for sharing your proposal. I have to admit I don't understand how it fits into OID4VP. Can you please share request and response examples?
@martijnharing just to follow up on the conversation in today's WG call, there's an example request that requests an encrypted response and has verifier authentication via the browser API here:
https://openid.github.io/OpenID4VP/openid-4-verifiable-presentations-wg-draft.html#appendix-A.3.2
and the response just comes back as an encrypted JWE as per the second example here:
https://openid.github.io/OpenID4VP/openid-4-verifiable-presentations-wg-draft.html#appendix-A.4
It's probably not super clear (for brevity the actual signed jwt request and encrypted jwe aren't shown in full), and the request for encryption is a combination of the response mode with jwt and the jwks with a "use": "enc"
key - do let us know if it's overly confusing.
@martijnharing just to follow up on the conversation in today's WG call, there's an example request that requests an encrypted response and has verifier authentication via the browser API here:
https://openid.github.io/OpenID4VP/openid-4-verifiable-presentations-wg-draft.html#appendix-A.3.2
and the response just comes back as an encrypted JWE as per the second example here:
https://openid.github.io/OpenID4VP/openid-4-verifiable-presentations-wg-draft.html#appendix-A.4
It's probably not super clear (for brevity the actual signed jwt request and encrypted jwe aren't shown in full), and the request for encryption is a combination of the response mode with jwt and the jwks with a
"use": "enc"
key - do let us know if it's overly confusing.
As I tried to acknowledge on the call yesterday, I suspect it is rather confusion for someone coming to this without familiarity with the many layers of OAuthy stuff that's been built on here. And effectively a first draft at a profile for the W3C Digital Credentials API that is building further on that. But as @jogu says, a request for encryption is conveyed with with a response mode of w3c_dc_api.jwt
and the jwks with a jwk with a "use": "enc"
. The resulting response with be JSON with a JWE as the value of the "response" member. And verifier authentication is achieved via signing the request (as a JWS/JWT that then is a member of the JSON request). Yes there's requests layered on requests and responses in responses. But that's the bed we've made for ourselves.
Hereby an example, all the cryptographic structures should be correct as well
Static RP key:
x: f8912ee0f912b6be683ba2fa0121b2630e601b2b628dff3b44f6394eaa9abdbc
y: c2149d29d6ff1a3e091135177e5c3d9c57f3bf839761eed02c64dd82ae1d3bbf
Ephemeral RP key:
x: 60e3392385041f51403051f2415531cb56dd3f999c71687013aac6768bc8187e
y: e58deb8fdbe907f7dd5368245551a34796f7d2215c440c339bb0f7b67beccdfa
d: de3b4b9e5f72dd9b58406ae3091434da48a6f9fd010d88fcb0958e2cebec947c
Ephemeral device key:
x: 5a88d182bce5f42efa59943f33359d2e8a968ff289d93e5fa444b624343167fe
y: b16e8cf858ddc7690407ba61d4c338237a8cfcf3de6aa672fc60a557aa32fc67
d: c1917a1579949a042f1ba9fc53a2df9b1bc47adf31c10f813ed75702d1c1f136
const credential = await navigator.identity.get({
digital: {
providers: [{
protocol: "openid4vp",
request: {
"vp_query_info": "eyJjcmVkZW50aWFscyI6IHsiYSI6IHsiZm9ybWF0IjogIm1zb19tZG9jIiwgIm1zb19tZG9jIjogeyJkb2N0eXBlX3ZhbHVlcyI6ICJjb20uZXhhbXBsZS5pZCJ9LCAiY2xhaW1zIjogW3sibmFtZXNwYWNlIjogImNvbS5leGFtcGxlLmVsZW1lbnRzIiwgImNsYWltX25hbWUiOiAibGFzdF9uYW1lIn0sIHsibmFtZXNwYWNlIjogImNvbS5leGFtcGxlLmVsZW1lbnRzIiwgImNsYWltX25hbWUiOiAiZG9jdW1lbnRfbnVtYmVyIn1dfX19",
"response_encryption": "eyJyZXNwb25zZV9tb2RlIjogInczY19kY19tZG9jXzEiLCAibm9uY2UiOiAiYXZvRFVWV1FvV2VQbmk2RzQ1UGZXQSIsICJqd2tzIjogeyJrZXlzIjogW3sia3R5IjogIkVDIiwgImNydiI6ICJQLTI1NiIsICJ4IjogIllPTTVJNFVFSDFGQU1GSHlRVlV4eTFiZFA1bWNjV2h3RTZyR2RvdklHSDQiLCAieSI6ICI1WTNyajl2cEJfZmRVMmdrVlZHalI1YjMwaUZjUkF3em03RDN0bnZzemZvIn1dfX0",
"verifier_authentications": [
[
"verifier_authentication_example",
"eyJhbGciOiAiRVMyNTYiLCAieDVjIjogIlZHaHBjMmx6Ym05MFlXTmxjblJwWm1sallYUmwifQ..iXpUwMEe9SpQilW6JJrl999Ev_efw7t7lDpJ45f9G8UvBKoEOv5LMef7jpr4HaOB-dK-iz5iCyi5bWpeLN3r8A"
]
]
}
}]
}
});
where vp_query =
{
"credentials": {
"a": {
"format": "mso_mdoc",
"mso_mdoc": {
"doctype_values": "com.example.id"
},
"claims": [
{
"namespace": "com.example.elements",
"claim_name": "last_name"
},
{
"namespace": "com.example.elements",
"claim_name": "document_number"
}
]
}
}
}
where response_encryption_parameters =
{
"response_mode": "w3c_dc_mdoc_profile_1",
"nonce": "avoDUVWQoWePni6G45PfWA",
"jwks": {
"keys": [
{
"kty": "EC",
"crv": "P-256",
"x": "YOM5I4UEH1FAMFHyQVUxy1bdP5mccWhwE6rGdovIGH4",
"y": "5Y3rj9vpB_fdU2gkVVGjR5b30iFcRAwzm7D3tnvszfo"
}
]
}
}
Authorization response:
{
"encrypted_data": "hJCzPYw8X3e-uqM1l-XPmXOvsUYMTq4NlfruMBZeA-TXUraPUlao4CJzi4zR-HGV7pKZZr1H6txdWXtTjNdOw_n2bO5Ojj_s4H4HgGqRMo_L85NAFRTixzPhzCweZPgIBzWLh81njj3x-C5KnyDgbnLbEfJXaVYp6KRQteXnj15Jj6heD4FTOsIDiIBaHeNGe7wSPTEbsnvI3MCnkw0RZza3bVW2u0HNVDKV2VNCH0XRTNrnuctkuVZwtBhm7EZSqkUNsGajZ65w9E7HGUu_9MlhYl2p_ft6fLaijnrj60m-deIoj7S_DHS5WDa3QpY9gPbIhYFWFiJqYWF9gTzcyD90QA6uEvjkGfgnVPi1EwPSgHLfhcRrWdJ6RVSGoHrDUQH6mTs5uoWn6ysJj0TQ7BG-zIyrIP-9owgNN4UMeihCyMtq91v6DKbzvhg6rH0IhVLjj3h9x1hha6KcNv0ySSeW7s6lgaNGqIxmE1I21FAUowfAgpZOT9_kjOq-EwnBG31xF3w8DHwJlcm2bm5E7RevSHoTodSbAthMg2K32AvXAKQo14uf3J32rl-AbsHhi2TzHFrdL8IuSbH4XamdOGJxBKgUVL6xjrjlvnGC9W7ZSGa4cTPyx0iYBMMTmhll0rivxACXqjZveGnw51WHDJm5i9xhZli1MC0hGdCHcn_eFdCXI2IQ8YFdhTDvv9btvNHLkAmOSZhQpeXlSWIPoz20NKZ9Lk565uUQakMXILaHYtnzI--1h-M34gvO7EODDjPzh9X7WhnE-_nvPmMs46Dnuhmi7Z0eSzT8wOX8f67BYyFwDEepyXDMg0XlJ8555GeQxOcLBpVUCEkLl1xuC0LG40qPNP-tyHc2zXXAU5tLpKQb2tLiK_ksSuw9wM5xtjCBNSzcorS1P97FTTqI4f8ly-ZYIPX85WTSEDpaaTzF1Fvpl_JfOjL06ZTZbtf4JnC0-biVFpu-5TMTHEQFa-ve_nMCftxR7YIh3ByxYzoLok0jRT7ntgnAhQSO8xP3jtPoFT3sLHw9t-cEzxQ7j-CkrSqHh1h2-vJsnJWQhtvN65LeehyKFRlxh7KZ6H66PbnlZlhnLlLcdu94FMa1XPj0OvWbpJHZ-jkJZJu9NhaIcUgQZC1CmZ69lDZGxHoE2OjrdIJ58Y3k-mnGL4hVehUjJCJMzj5RpoUUeEDggGBPm_lc-ePf2gEIXqUaCikuxSiZ7uDfxCv2c0izoFGrMVY-Fx3KarQpGhs4QutQAxin1hahqvtx-IVwBI1FzaKNTU7oqI-4vNVl4lFu-IRQ5ofG1uYpyBgOfGNp4L_i_YhgTh_Gp0_HL4VkyhsW_8l9ZgD2SomPyMOFw5TL90PPTO55hf4Q6w0lVOK81SgvwTHaAzqtDJaNC07inTLGzO6erxjZiOIB6V1T9-dA46PsDUm98vzpR2JHK2jGNvVb6VnrgC-Ej7Fkco2Kz8IoY6iMNaOaA-XZgRiYRTdpdLeZvMK24JoLzdZMZQLkyRqM2PofsD5wvSU6HnDR7-eOFw-F09nc7HDlMoiI_NVb2gWja0KAk8Njxdeg4K5vdtjWbwOZyskSw_8iFfW10RWHq4MUbp-XcxpyO6yg_RTzE-0CALyDo7-BM91CJRYCkg__Bdy1I89e9HkbemN-n3oozbqd0nj1YuquFaqT8nZtqp3LDQS1zEdMyFB5z3Z6gSIfOKizE0AyVeiuefUJI6EuulPMYrNlsrRMFa2XQyQjjlSwcVJ7FV2_3p-WEY1anfVcz2-my3LA05mztbVQUaYUl-K48FGpJa6PGpB2UvoPFrd5wgVajwtvqOoZr2skOpOuJIX-iRobgR4wQVs1Sgm89NaOegW_uDWjv9OQhCRRSicoTtG4-DVBPKNPk3ZTprNf7czkI-FnuT8ujbZfSRSNLZUPc_wRovgChH-GYIE7IlCQwN4pZZzFP8mzx7buM8YUicbl5wxEK4PcVQcObgYroyghM9LtcVC3izJYiYaKlEaCfF8M5zdw7bET3CPr8X0XvUmsPon4Kp6iur1tAC7O-W8ptC9xf-2UOm_hR42nFN6B6eKMhmAFNH2D05nY-cPckT511RKYh-RH3xaMMMt6jUtkozsvKbmBfihZkCqUEjf84v0-Z4sUx9ufE5U1Hg_BLpfeFcGMno4nWGZ9hED3UTNxXR-QyXYb71ObVcfPWaogVb48R_OOceaV-PloOwkttDE9x-pqv2XK7jXhL44gk08rV1p6DoknXr90lnG24lXc6Y9dTPwEPI3w67_uBcaEEo6rfMEEJOcl--tYQ0-lqf30WKnfqc61QBazI3xqvHxEKG-lJQDR-C4QGE7GLkRIQVLRAeC8WO0ANwE9E9cbapN-3OapdGbZU0EEyxvU9DySgp8acjRV_VWFeTSYmLIXZsoxGMoqkTi_xLOWFe3CIzcYnTVpt92LuKY0He4-aQoiMZrHGXHhI2yqiepIvQKJDexi-4r16guKYSM5ancro-41EUZfe6WWT4LlmQcsM2xKrrW1674LfdhoFlB9ZCj_AfRTzWCq79FPpx6q6BkTzqKv8uLO3r2FGvg4V4xhOyj7gu2V-en_Rvcvc8EL_SnHW_rnFMBV1OFcbkwj4AND7C2P_rq6-wRzVTEQc3R-hAZMyihnT-KksQr8hUbWolvGp5lL4jpAc1j73SARHg2y2-QCBmyt29oQOaqSGDm0KWFdFqNpMAgguo1_jAQhhow3n6XFVSjQDJ_VIfe15nev1qEji2vjv7can_gEMs9kzY16a7h-flqX7PBdQ07UGr9Bt1d9uCPXCt9_QvaoZAbq4zNT7FXhntxGZf72Fx8Esz0kaPKWu6dodnDFUZllWhb6AnPbHJ29hwQ3rIKwrwlGLKbq7pewgzxgoFIhisWvP2N2rn03I9BoQZItWYc6Ca5BCW0MoNYJXnpktbGYF-WB10UaSaiarw4FsXU6rn_z1k2wU6juHANN8y_M7TkGxpxgt1G0MZLwIE_LGqPH_cW68YyH5DNQqOSSQDKjqfvCXdyE0S8s69sWC45fEnHt4tq5lbFFmgU_ooq9BKjMmktDPy9y9RAVLFP0veQGLv0JSIaWiJPpvelva0RA1aRyNnObzqEY9NI7O5fkBjK92xgXs-XOhJ8TMQrWtsWNgld8KBPXiLCrU4cbd41Sae8U-EOwA1Qerdt8LmoPkXB_aFvvzoBozCbM-X6mLvqCsC7v7tdUkwALFN0DuCTGWde-JhDWEUohm62mN8U8vXD5gCVOXRhlWFtC5hBNk0MV7Lb6E8c5D8cuAkItqUEgUI_P-RL5ESQ_lrsSYhmubdpAEx_s2zyhNvUTFfskonRrP4cMWH4ogxeiX-ryl7P5-9vkhoBy91k18U8K8ADtJZDLIM1n8OVSXgP_RknfwEcNTZVrSPdJYrjl7S7cR4Nn6abnbaGvADvK9u4F2aGVPwMAAsSgJt2qDbrBBpzxxaI1ttbLwTzGdy-e2AHdlVvqpMLMAUw99F47hnoq11rjI2tbpkjA3NUUpGSPhRfE_x0zRee13RJ9dBy6zLue1RZQYPC8otP1DvIwDC2yo98-8-WhAIcd5aK_s0DFbt3VpjYpNzuGZpRsUfFGijf-mp-KK3c1oK4QZkre5XrS4OprM3BI97AdL9WsC0ixtqEGVdVhTpbJD2oncbeXXc2mnSF5-8hhEQMcL7wcRezFbrK3yP2orKt_FXQG-yuApHBlNLJn0tmzz1NVNevG7BRmeU0Nr2Goi2nHTkoFjKS-_zcXEqq7q0PXtV77E_1o_d-YsFg0L91cSkyMN83FhJNsmz9EQr7ajNmEJVVZEEFfZcnk0ZZkwqjWfTtFCa6N5hX4buoeC-OF_qp__69Vll-VTPiV4QEsFB_cAce_air_ouwV8Pg4SeManNWEIfQ60fmJLe8NVX8rZp6X6m0iI3lqRqDXfYPgLHF_vjXPINE80Ng",
"jwks": [
{
"kty": "EC",
"crv": "P-256",
"x": "WojRgrzl9C76WZQ_MzWdLoqWj_KJ2T5fpES2JDQxZ_4",
"y": "sW6M-Fjdx2kEB7ph1MM4I3qM_PPeaqZy_GClV6oy_Gc"
}
]
}
where encrypted data contains:
{
"vp_token": "o2d2ZXJzaW9uYzEuMGlkb2N1bWVudHOBo2dkb2NUeXBldW9yZy5pc28uMTgwMTMuNS4xLm1ETGxpc3N1ZXJTaWduZWSiam5hbWVTcGFjZXOgamlzc3VlckF1dGiEQ6EBJqEYIVkB9DCCAfAwggGVoAMCAQICFCuL9vlL42zupOgdrQ3xCJSsYjxrMAoGCCqGSM49BAMCMCMxFDASBgNVBAMMC3V0b3BpYSBpYWNhMQswCQYDVQQGEwJVUzAeFw0yMDEwMDEwMDAwMDBaFw0yMTEwMDEwMDAwMDBaMCExEjAQBgNVBAMMCXV0b3BpYSBkczELMAkGA1UEBhMCVVMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASs56tzQOXZZIxacqmm9WdFx6rUNqA6Q-_qd7X6e4jwGX1X2Jg-GzfTpTn01Yg2XjjLv1uU1oxUe1vIcx3NLxRro4GoMIGlMB4GA1UdEgQXMBWBE2V4YW1wbGVAZXhhbXBsZS5jb20wHAYDVR0fBBUwEzARoA-gDYILZXhhbXBsZS5jb20wHQYDVR0OBBYEFBTikBemw1Yh_8emhre3LbBs0SNRMB8GA1UdIwQYMBaAFFT6I4OgTCjg2TB5ImHIDEiB0sALMA4GA1UdDwEB_wQEAwIHgDAVBgNVHSUBAf8ECzAJBgcogYxdBQECMAoGCCqGSM49BAMCA0kAMEYCIQCPHnIhN9_eBeeRP2I9xjml04mTm7T2aTZ_OQlYDPcv8wIhAOKOLn7UGjZX4Gy5XC4pIduJPs9c1RB-CnxICD0pXbAfWQVu2BhZBWmmZ3ZlcnNpb25jMS4wb2RpZ2VzdEFsZ29yaXRobWdTSEEtMjU2bHZhbHVlRGlnZXN0c6Jxb3JnLmlzby4xODAxMy41LjG4GQBYIHUWczO0e2wr-4bszB9DjPV68FU3GsVeHjWeIPJUrc6_AVggZ-U51hOevRMa70QbRFZF3YMbKzdbOQyl72J5sgXtRXECWCAzlDct23gFPzbV2Gl4DmHtoxPUSjkgkq2OBSei-_5VrgNYIC41rTxOUUu2exqdtRznTky5txRuQaxS2snOhrhhPbVVBFgg6lwzBLt8So3LUcTBO2UmT4RVQTQTQgk8ynhuBY-sLVkFWCD65If2i3oOh6dJd05W6eHcOo7Ht35JDSHw4dNHVmGqHQZYIH2D5Qeud9uBXeTYA7iFVdBRHYlMiXQ59XdAVkFqHHUzB1gg8FSaFF8c91y-7_qIHUhX3UONYnzzIXSxcxxMOOEsqTYIWCC2jIr8sqr3xYFBHSh33vFVvi6xIaQrybpbcxI3fgaPZglYIAs1h9HdDCoHo1v7Eg2ZoKv7XfVoZbt_oVzItWpm324MClggyYoXDPNuEau3JOmKdaU0PforbtPfLs-7jvLuVd1ByIELWCDsVuZg__vpiaCSRiQUKbeqYrgZgNIK7Pz6L7iK1B-1bQxYIBmXqvlCy2RUcXF1b5flYwz5CpTPI7yo-dYvqmal-2EcDVggb3eIRkKaG1fS6s__VKpacTsXXepM8SufQZr61hwl2r8OWCDP9AYLGK5pE8C5VkVfare7Shw6sAeXmAStqag0jdhGYw9YIDQDz7_Er-dI2axeIiReMvIzVYre0AS9CjjEaUJc5RjCEFggzuXafEWluj70StratJsExBGghXvX25HWtNjewzu1deARWCD5Tf2xEcc34dyzGno8v0l0coMWmgC0x4UtM3mS1x48qRJYICK-wbv-pZhZLArhZ4e9IWBxRYlY7ijbCiJ1qr_xQQQdE1ggNaiui6IgCQFr5OS-vuZPeMRAWsLvzZkonD1mXdnwKMAUWCDtzy20bxYGvq_cWHbkWTqTcLKgZkH6_qBwoXwKAgwfohVYIHbQll4QKja4ZuE4tch70zpQiwg37SZS7jUqWHNsa_lwFlggiXl2t2g5LJ1XYJBbpKjaMRKMtbZmWGW_0JEGI8tv4JoXWCCoG12PCgIJMdeqrf1-bbIKBux7JIZiN1ftZNuA1Xoe1xgYWCAIhVIAFVhiBJtTDRh67JtT5c4A9VChpN3vmbhpx0Z_jHdvcmcuaXNvLjE4MDEzLjUuMS5hYW12YaUAWCDWdov_0Gyf252joOY6Dt6_xPk81uDBEt3xBdCmw0EzLAFYIFjUqmvOEx_IiPQxPiKHEHkn4pGaV37iMTi_tkTYjRriAlggng1UErwg85HQzPagMREWYQ8veffxoWSR0qvkawPc5xMDWCAcqVIOi7o_Bbr67etasEXQN7LApg1sV_tT6a6ylfn-BARYIDrmBbcfq-7XzSYZWAvJ3KdqXxDEC_iTlowfMLfTwmOTbWRldmljZUtleUluZm-haWRldmljZUtleaQBAiABIVggljE9bGPiTjNydCv9saM7osiX3NaKuMdT5PvUjcprf5oiWCAfsyae3UGIV94bOaTkpEuS-khMqnIsIoKI8B0MA6LD1mdkb2NUeXBldW9yZy5pc28uMTgwMTMuNS4xLm1ETGx2YWxpZGl0eUluZm-jZnNpZ25lZMB0MjAyMC0xMC0wMVQxMzozMDowMlppdmFsaWRGcm9twHQyMDIwLTEwLTAxVDEzOjMwOjAyWmp2YWxpZFVudGlswHQyMDIxLTEwLTAxVDEzOjMwOjAyWlhAtrMhx1htTWhEQlOQBoLxRghQbBGnoOGH4rRmGAdhwfjqtFlrm2jbhm1GFRkGYzSqVKanHE7gr3fPWkGjluFvlWxkZXZpY2VTaWduZWSiam5hbWVTcGFjZXPYGEGgamRldmljZUF1dGihb2RldmljZVNpZ25hdHVyZYRDoQEmoPZYQCLmcjhi89rHd_VJx4IDDapRgaioeNK4xrpB61cN12AAdAmGcnzj-keTFP4Cu4c94h84m54GrhBUjiEFdS1kUnJmc3RhdHVzAA"
}
Based on the comments a few changes are made: Instead of using a jwk, a jwks is used. Since only a single key is present, I couldn't find a hard requirement that "use"="enc" has to be present, so that's left out for now. The response_mode was left out in the original proposal since the two response modes defined in A.2 (w3c_dc_api and w3c_dc_api.jwt) both do not apply but leaving it out defaults to 'fragment' which is also not accurate. Therefore the response_mode parameter is used to indicate the profile that's used, the naming of that type is changed to be in line with the parameters currently defined in A.2.
This example uses the updated request structure that's currently under development. It also uses the 'verifier_authentication_example' mechanism, that allows to authenticate the verifier (through its key material), without needing to sign the full request (including the vp_query), which was discussed at IIW as one of the mechanisms to be supported.
Hi Martijn
Thanks!
It might be worth thinking about how we progress this. In particular I think it's likely that anything that isn't mdoc specific (e.g. adding a new way to authenticate the verifier) should be split out into a separate issue that can investigate if that mechanism should be added to the browser API appendix and/or the core of OID4VP.
I'm not clear why response_mode=w3c_dc_api.jwt
can't be used here, but if we need changes to response modes that should probably also be handled separately.
The mdoc profile itself should only build on top of what is already in the rest of the standard, specifying how to use the existing standard with mdoc - i.e. not specifying new behaviours unless they're dealing with an mdoc-specific problem.
Thanks for the suggestion, indeed if there are parts of the requirements and definitions that are in the profile proposal that instead should go in the browser-api annex itself then that's of course just as good (or even better). In order to make a concrete separate issue, which parts of the profile should those be exactly?
On the response_mode, the current text says: "The value of the response_mode parameter MUST be w3c_dc_api when the response is neither signed nor encrypted." Since the response is encrypted, this requirements does not apply. The next part says: "and w3c_dc_api.jwt when the response is signed and/or encrypted as defined in [Section 6.3]." Most requirements in section 6.3 seem to be not applicable since [JARM] and section 6.3.1 define response modes that are all either using redirects or posts to transmit the response (i.e. none of them use the w3c_dc_api.jwt response mode). But since section 6.3 does talk about encrypting the response, one way to interpret this requirement is to say that it effectively means something like "whenever you do encryption (or signing) of the response, the response_type value MUST be w3c_dc_api.jwt". If that's the case then we can change the response type value to w3c_dc_api.jwt in the profile text and separately add back the response encryption type parameter “mdoc_profile_encryption_1” for this profile that fixes all the hpke encryption parameters to a single choice.
In order to make a concrete separate issue, which parts of the profile should those be exactly?
vp_query_info, response_encryption, response_encryption_parameters, verifier_authentications, type, jwt, are all features that duplicate existing openid4vp features and should be separate from mso_mdoc profile of the browser API profile of openid4vp.
sentences like The vp_token contains the base64url encoded DeviceResponse as defined in 18013-5.
is what we would need in mso_mdoc profile I think.
JARM is defined separately from any redirects, so w3c_dc_api.jwt is the response_mode to use when returning encrypted responses over the browser API.
Discussed in a WG call, agreed that next steps are to go back to smaller questions that led to the proposal such as those below (not capturing all of those, and my wording might not be accurate):
so that we can start clarifying things in the spec for things that are already defined but are not clear enough. @martijnharing feel free to open new issues for those items that you already know would require a dedicated discussion. if not sure, feel free to start by posting in this issue.
also discussed that these things probably need to be fixed in general in the spec (outside the mdoc profile)
Hereby some further explanation for those questions, some possible ways forward and explanations for the choices made in the proposals.
For item 1, "how to pass an encryption key in a trusted way in an unsigned request".
This is mentioned in the WG10 ask as: "There must be an option for the app to authenticate the key received from the RP to be used for response encryption. Mechanisms to be supported are:
This means that we need to authenticate the information used for response encryption and transaction security. In the context of OpenID4VP, this includes the jwk for response encryption, the response encryption cryptographic requirements (e.g. algorithm, encryption profile etc), the nonce, and (if present) the expected origin. The structure (or structures, see also the next item) that contain this authentication information needs a mechanism (e.g. type) to indicate which information is being authenticated in order to build up the correct structure to be signed.
The proposal does not use JAR for a few reasons, an important one being that JAR requires the full structure to be signed. This means that it's not possible to only sign the response encryption information (i.e. the query-language structure must always be signed as well).
In the proposal the authentication is done by signing the "response_encryption_paramaters" structure. This intermediate structure was used to facilitate signing the correct information but means a regrouping of the OpenID elements like nonce and jwks, which is not the preferred direction as indicated by the group. The other downside of this approach is that it this doesn't work well with the requirement for the elements to be encoded as WebIDL elements. The solution that would likely address all of these concerns is to require a form of JSON canonicalization before creating and verifying the signature. Is something like RFC 8785 a possible solution for such an approach?
If that's possible, we can include the values of nonce, jwks, response encryption parameters, client_id, client_id_scheme, the response encryption parameters and the vp_query directly in the data to be signed structure for the verifier_authentication structure. This would also mean that we can include all of these parameters in the same way as is currently defined for the authorization_request, instead of needing the 2 new vp_query_info and response_encryption parameters. For the verifier_authentication structure, the type element in the verifier_authentication structure would determine which of these elements must be included in the signature calculation, in order for the wallet to be able to verify the signature.
Issue#92 was mentioned, but that seems to address a different issue than the problem of authenticating the encryption information.
For item 3 "what if verifier wants to pass multiple trust models, hoping one is supported by the wallet?"
This is implicitly mentioned in the WG10 ask since the 18013-5 request structure supports multiple RP authentication signatures.
Not having the ability to support multiple RP authentication signatures would mean that it's not possible to request documents that use different trust models, or request documents from issuers (e.g. regions) that have different trust models. Not having those abilities would be a significant limitation of the protocol.
Most of the consequences and possible solutions are similar to the ones mentioned in item 1, since having multiple RP authentication signatures seems to not be supported by the JAR specification.
The proposal addresses this by defining an array of verifier_authentication elements, each of which can contain a signature for a trust model. As the elements that are signed by these structures is dynamic (see item 1), this mechanism supports both the scenario of signing the encryption information, as well as also signing the vp_query.
For item 2, "which JARM response mode to use to return encryption response over the browser api"
Annex A mentions that "[..] w3c_dc_api.jwt when the response is signed and/or encrypted as defined in Section 6.3." Section 6.3 then mentions that JARM MAY be used to encrypt the authorization response. The JARM specification itself specifies response modes that use redirects or form_post. Section 6.3.1 defines the direct_post mode, which uses an HTTP POST mechanism. So none of the JARM response mode mechanisms in section 6 seem to be applicable.
If the intention of Annex A is to use the JARM specification, but to use a different response mode mechanisms that uses the browser api for transmission, we would also have to address a number of requirements in the JARM spec that are either not applicable or can have adverse effects in the context of using the browser api. For example, JARM requires the aud element to be present and match the client ID, while Annex A requires that the client ID must be omitted when the requset is unsigned.
The proposal performs the response encryption using just 2 parameters in the response: the key used for encryption and the encrypted blob itself. Using the optional JARM mechanism to provide the encryption would mean duplicating algorithm information (e.g. the exact HPKE mode, the encryption profile) which seems to result in a more complex structure to implement and verify than what's currently proposed. The proposal also defines a response mode parameter that defines both the encryption algorithm to be used, as well as how what parameters are included in the response encryption, e.g. what the contents is of the info parameter of the HPKE operation.
Apologies @martijnharing, some of my inability to understand the resistance to JARM and attachment to HPKE in this issue came through at the end of the call when the different https://github.com/openid/OpenID4VP/issues/216 was being discussed. Hopefully the clarifications that @selfissued offered to make there will be helpful in this context too.
This proposal is based on a discussion with @jogu @martijnharing @awoie @danielfett @bc-pi:
We would like to omit canonicalization of the request, that's why the basis of the proposal is to use the multi signature feature provided by the JWS JSON Serialization.
The OID4VP request
{
"expected_origins": [
"https://origin1.example.com",
"https://origin2.example.com"
],
"response_type": "vp_token",
"response_mode": "w3c_dc_api.jwt",
"nonce": "n-0S6_WzA2Mj",
"client_metadata": {
"vp_formats": {
"vc+sd-jwt": {
"sd-jwt_alg_values": [ "PS256" ],
"kb-jwt_alg_values": [ "PS256" ]
}
},
"jwks": {
"keys": [
{
"kty": "EC",
"crv": "P-256",
"x": "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
"y": "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
"use": "enc",
"kid": "1"
}
]
}
},
"presentation_definition" or "vp_query": {}
}
would not contain client_id
and client_id_scheme
. It would be put into the payload
element of the JSON Serialization structure.
const credential = await navigator.identity.get({
digital: {
providers: [{
protocol: "openid4vp",
request: {
"payload": "eyAiaXNzIjogImh0dHBzOi8...NzY4Mzc4MzYiIF0gfQ",
"signatures": [
{
"protected": "eyJhbGciOiJFUzI1NiJ9",
"header": {
"client_id": "987647789",
"client_id_scheme": "x509_san_dns"
},
"signature": "PFwem0Ajp2Sag...T2z784h8TQqgTR9tXcif0jw"
},
{
"protected": "eyJhbGciOiJFUzI1NiJ9",
"header": {
"client_id": "https://rp.federation.eu",
"client_id_scheme": "entity_id"
},
"signature": "irgtXbJGwE2wN4Lc...2TvUodsE0vaC-NXpB9G39cMXZ9A"
}
]}
Every "signatures" object has the additional data for a certain RP authentication credential (protected or unprotected). Underneath every "signatures" object, the "signature" object has the respective signature over "payload" and "protected". "protected" could contain the response encryption key, so it is signed and authenticated.
Open Questions:
traditional
OID4VP flow and the DC API?I've split the multiple RP authentication part out into issue https://github.com/openid/OpenID4VP/issues/248 as it seems to be more generally applicable. (We should probably create issues for any other generally applicable parts.)
Agreed on today's call that Martijn could open a PR.
Agreed on today's call that Martijn could open a PR.
While that is true, it was at the very end of the call at a point that I suspect many participants had lost the will to try to contribute. I can say with some certainty that that's where I was at that point in the call. I can also say with some certainty that it's not clear what that PR might entail. But I really hope that any such work will consider @jogu's very reasonable and appropriate comment from a month ago: "[that the] mdoc profile itself should only build on top of what is already in the rest of the standard, specifying how to use the existing standard with mdoc - i.e. not specifying new behaviours [behaviors] unless they're dealing with an mdoc-specific problem. [and even then considering if they are really mdoc-specific problems or just seem that way due to being viewed through an mdoc-specific lens]."
Thanks @bc-pi. Yeah, sorry, my previous comment was probably overly brief, a side effect of trying to get through too much on yesterday's call. To record the other things I said on the call:
The profile is expected to define things for interoperability like which authorization_encryption_alg_values_supported
value must be used for mdl, and what goes in the SessionTranscript - very similar to what part 7 does (although I really hope this ends up a lot shorter than part 7). That is to say, a strict profile of what is already in the rest of the spec, not introducing new features.
Hopefully the thoughtful work that @selfissued did in #243 to clarify signing and encryption with JARM responses will help with any persistent misunderstanding that's occurred in this context.
I talked privately with Martijn a bit more about this just to check we didn't have any unsettled items left but it looks like we still need to discuss the encryption mechanism more in the working group to reach a consensus, so I've moved this to 'discuss' status.
discussed at IIW.
The scope of the HAIP specification is to provide a full set of requirements for the full life cycle (provisioning, presentment) of SD-JWT VC. It includes requirements on a large range of issues going way beyond what we need for mdoc, which is only how to use the DC-api profile of openid when you want to present an mdoc. Those scopes are very different, so I don’t understand why the HAIP specification is a good place for the mdoc profile dc-api profile compared to an annex of openid4vp.
can we move this discussion to #327 ?
ISO/IEC SC17/JTC1 WG10 had an in-person meeting in Korea in late June where a demo of the Digital Credentials API was provided (also including cross-device). WG10 asked OIDF if they can help with the following:
As a member of WG10 (I'm not speaking on their behalf) and OIDF/DCP, I would support this ask, especially to facilitate harmonization between OIDF and ISO.
Before jumping into the detailed requirements and how to address them, I think OIDF/DCP should think about: 1) are we going to support this ask (I do), 2) and how to address this structurally. Structurally, it could be done in the following way but feedback welcome:
Option 1:
Option 2:
Beyond the above, we can think about harmonization between HAIP and this new mdoc-specific profile, especially wrt the Digital Credentials API profile which I assume HAIP will also want to make some choices in the future. But I see this not as something we necessarily have to decide right away.
@Sakurann @jogu @tlodderstedt @martijnharing @tplooker @paulbastian @GarethCOliver @davidz25 @sbahloul