diff --git a/openid-4-verifiable-credential-issuance-1_0.md b/openid-4-verifiable-credential-issuance-1_0.md index 86fbe39b..af4d6f81 100644 --- a/openid-4-verifiable-credential-issuance-1_0.md +++ b/openid-4-verifiable-credential-issuance-1_0.md @@ -799,10 +799,7 @@ The issued Credential SHOULD be cryptographically bound to the identifier of the Note: Claims in the Credential are about the subject of the Credential, which is often the End-User who possesses it. -For Cryptographic Key Binding, the Client has the following options defined in (#credential-request) to provide Cryptographic Key Binding material for a requested Credential: - -1. Provide proof of control alongside key material. -1. Provide only proof of control without the key material. +For Cryptographic Key Binding, the Client has different options to provide Cryptographic Key Binding material for a requested Credential within a proof of a certain proof type. A proof type may provide the cryptographic public key(s) either with corresponding proof(s) of possession or with key attestations. Proof types are defined in (#proof-types). ## Credential Request {#credential-request} @@ -909,178 +906,6 @@ The Client MAY request encrypted responses by providing its encryption parameter The Credential Issuer indicates support for encrypted responses by including the `credential_response_encryption` parameter in the Credential Issuer Metadata. -### Proof Types {#proof-types} - -This specification defines the following proof types: - -* `jwt`: A JWT [@!RFC7519] is used for proof of possession. When a `proofs` object is using a `jwt` proof type, it MUST include a `jwt` parameter with its value being a non-empty array of JWTs, where each JWT is formed as defined in (#jwt-proof-type). -* `ldp_vp`: A W3C Verifiable Presentation object signed using the Data Integrity Proof [@VC_Data_Integrity] as defined in [@VC_DATA_2.0] or [@VC_DATA] is used for proof of possession. When a `proofs` object is using a `ldp_vp` proof type, it MUST include an `ldp_vp` parameter with its value being a non-empty array of [W3C Verifiable Presentations](https://www.w3.org/TR/vc-data-model-2.0/#presentations-0), where each of these W3C Verifiable Presentation is formed as defined in (#ldp-vp-proof-type). -* `attestation`: A JWT [@!RFC7519] representing a key attestation without using a proof of possession of the cryptographic key material that is being attested. When a `proofs` object is using an `attestation` proof type, the object MUST include an `attestation` parameter with its value being an array that contains exactly one JWT that is formed as defined in (#keyattestation-jwt). - -There are two ways to convey key attestations (as defined in (#keyattestation)) of the cryptographic key material during Credential issuance: - -- The Wallet uses the `jwt` proof type in the Credential Request to create a proof of possession of the key and adds the key attestation in the JOSE header. -- The Wallet uses the `attestation` proof type in the Credential Request with the key attestation without a proof of possession of the key itself. - -Depending on the Wallet's implementation, the `attestation` may avoid unnecessary End-User interaction during Credential issuance, as the key itself does not necessarily need to perform signature operations. - -Additional proof types MAY be defined and used. - -#### `jwt` Proof Type {#jwt-proof-type} - -The JWT MUST contain the following elements: - -* in the JOSE header, - * `alg`: REQUIRED. A digital signature algorithm identifier such as per IANA "JSON Web Signature and Encryption Algorithms" registry [@IANA.JOSE]. It MUST NOT be `none` or an identifier for a symmetric algorithm (MAC). - * `typ`: REQUIRED. MUST be `openid4vci-proof+jwt`, which explicitly types the key proof JWT as recommended in Section 3.11 of [@!RFC8725]. - * `kid`: OPTIONAL. JOSE Header containing the key ID. If the Credential shall be bound to a DID, the `kid` refers to a DID URL which identifies a particular key in the DID Document that the Credential shall be bound to. It MUST NOT be present if `jwk` is present. - * `jwk`: OPTIONAL. JOSE Header containing the key material the new Credential shall be bound to. It MUST NOT be present if `kid` is present. - * `x5c`: OPTIONAL. JOSE Header containing a certificate or certificate chain corresponding to the key used to sign the JWT. - * `key_attestation`: OPTIONAL. JOSE Header containing a key attestation as described in (#keyattestation). - * `trust_chain`: OPTIONAL. JOSE Header containing an [@!OpenID.Federation] Trust Chain. This element MAY be used to convey key attestation, metadata, metadata policies, federation Trust Marks and any other information related to a specific federation, if available in the chain. When used for signature verification, the header parameter `kid` MUST be present. - -* in the JWT body, - * `iss`: OPTIONAL (string). The value of this claim MUST be the `client_id` of the Client making the Credential request. This claim MUST be omitted if the access token authorizing the issuance call was obtained from a Pre-Authorized Code Flow through anonymous access to the token endpoint. - * `aud`: REQUIRED (string). The value of this claim MUST be the Credential Issuer Identifier. - * `iat`: REQUIRED (number). The value of this claim MUST be the time at which the key proof was issued using the syntax defined in [@!RFC7519]. - * `nonce`: OPTIONAL (string). The value type of this claim MUST be a string, where the value is a server-provided `c_nonce`. It MUST be present when the Wallet received a server-provided `c_nonce`. - -The Credential Issuer MUST validate that the JWT used as a proof is actually signed by a key identified in the JOSE Header. - -The Credential Issuer SHOULD issue a Credential for each cryptographic public key specified in the `attested_keys` claim within the `key_attestation` parameter. - -Cryptographic algorithm names used in the `proof_signing_alg_values_supported` Credential Issuer metadata parameter for this proof type SHOULD be one of those defined in [@IANA.JOSE]. - -Below is a non-normative example of a `proofs` parameter (with line breaks within values for display purposes only): - -```json -{ - "jwt": [ - "eyJ0eXAiOiJvcGVuaWQ0dmNpLXByb29mK2p3dCIsImFsZyI6IkVTMjU2Iiwiand - rIjp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ4IjoiblVXQW9BdjNYWml0aDh - FN2kxOU9kYXhPTFlGT3dNLVoyRXVNMDJUaXJUNCIsInkiOiJIc2tIVThCalVpMVU - 5WHFpN1N3bWo4Z3dBS18weGtjRGpFV183MVNvc0VZIn19.eyJhdWQiOiJodHRwcz - ovL2NyZWRlbnRpYWwtaXNzdWVyLmV4YW1wbGUuY29tIiwiaWF0IjoxNzAxOTYwND - Q0LCJub25jZSI6IkxhclJHU2JtVVBZdFJZTzZCUTR5bjgifQ.-a3EDsxClUB4O3L - eDD5DVGEnNMT01FCQW4P6-2-BNBqc_Zxf0Qw4CWayLEpqkAomlkLb9zioZoipdP- - jvh1WlA" - ] -} -``` - -where the decoded JWT looks like this: - -```json -{ - "typ": "openid4vci-proof+jwt", - "alg": "ES256", - "jwk": { - "kty": "EC", - "crv": "P-256", - "x": "nUWAoAv3XZith8E7i19OdaxOLYFOwM-Z2EuM02TirT4", - "y": "HskHU8BjUi1U9Xqi7Swmj8gwAK_0xkcDjEW_71SosEY" - } -}.{ - "aud": "https://credential-issuer.example.com", - "iat": 1701960444, - "nonce": "LarRGSbmUPYtRYO6BQ4yn8" -} -``` - -Here is another example JWT not only proving possession of a private key but also providing key attestation data for that key: - -```json -{ - "typ": "openid4vci-proof+jwt", - "alg": "ES256", - "kid": "0", - "key_attestation": -}. -{ - "iss": "s6BhdRkqt3", - "aud": "https://server.example.com", - "iat": 1659145924, - "nonce": "tZignsnFbp" -} -``` - -#### `ldp_vp` Proof Type {#ldp-vp-proof-type} - -When a W3C Verifiable Presentation as defined by [@VC_DATA_2.0] or [@VC_DATA] signed using Data Integrity is used as key proof, it MUST contain the following elements: - -* `holder`: OPTIONAL. MUST be equivalent to the controller identifier (e.g., DID) for the `verificationMethod` value identified by the `proof.verificationMethod` property. -* `proof`: REQUIRED. The proof body of a W3C Verifiable Presentation. - * `domain`: REQUIRED (string). The value of this claim MUST be the Credential Issuer Identifier. - * `challenge`: REQUIRED when the Credential Issuer has provided a `c_nonce`. It MUST NOT be used otherwise. String, where the value is a server-provided `c_nonce`. It MUST be present when the Wallet received a server-provided `c_nonce`. - -The Credential Issuer MUST validate that the W3C Verifiable Presentation used as a proof is actually signed with a key in the possession of the Holder. - -Cryptographic algorithm names used in the `proof_signing_alg_values_supported` Credential Issuer metadata parameter for this proof type SHOULD be one of those defined in [@LD_Suite_Registry]. - -Below is a non-normative example of a `proofs` parameter: - -```json -{ - "ldp_vp": [ - { - "@context": [ - "https://www.w3.org/ns/credentials/v2", - "https://www.w3.org/ns/credentials/examples/v2" - ], - "type": [ - "VerifiablePresentation" - ], - "holder": "did:key:z6MkvrFpBNCoYewiaeBLgjUDvLxUtnK5R6mqh5XPvLsrPsro", - "proof": [ - { - "type": "DataIntegrityProof", - "cryptosuite": "eddsa-2022", - "proofPurpose": "authentication", - "verificationMethod": "did:key:z6MkvrFpBNCoYewiaeBLgjUDvLxUtnK5R6mqh5XPvLsrPsro#z6MkvrFpBNCoYewiaeBLgjUDvLxUtnK5R6mqh5XPvLsrPsro", - "created": "2023-03-01T14:56:29.280619Z", - "challenge": "82d4cb36-11f6-4273-b9c6-df1ac0ff17e9", - "domain": "did:web:audience.company.com", - "proofValue": "z5hrbHzZiqXHNpLq6i7zePEUcUzEbZKmWfNQzXcUXUrqF7bykQ7ACiWFyZdT2HcptF1zd1t7NhfQSdqrbPEjZceg7" - } - ] - } - ] -} - -``` - -#### `attestation` Proof Type {#attestation-proof-type} - -A key attestation in JWT format as defined in (#keyattestation-jwt). - -When a key attestation is used as a proof type, it MUST contain the `c_nonce` value provided by the Credential Issuer in its `nonce` parameter. - -Below is a non-normative example of a `proofs` parameter (with line breaks within values for display purposes only): - -```json -{ - "attestation": [ - "" - ] -} -``` - -The Credential Issuer SHOULD issue a Credential for each cryptographic public key specified in the `attested_keys` claim within the `key_attestation` parameter. - -### Verifying Proof {#verifying-key-proof} - -To validate a key proof, the Credential Issuer MUST ensure that: - -- all required claims for that proof type are contained as defined in (#proof-types), -- the key proof is explicitly typed using header parameters as defined for that proof type, -- the header parameter indicates a registered asymmetric digital signature algorithm, `alg` parameter value is not `none`, is supported by the application, and is acceptable per local policy, -- the signature on the key proof verifies with the public key contained in the header parameter, -- the header parameter does not contain a private key, -- if the server had previously provided a `c_nonce`, the nonce in the key proof matches the server-provided `c_nonce` value, -- the creation time of the JWT, as determined by either the issuance time, or a server managed timestamp via the nonce claim, is within an acceptable window (see (#key-proof-replay)). - -These checks may be performed in any order. - ## Credential Response {#credential-response} Credential Response can contain one or more Credentials depending on the Credential Request. @@ -2544,6 +2369,180 @@ To use the Wallet Attestation towards the Authorization Server, the Wallet MUST The `sub` claim of the Wallet Attestation JWT is picked by the Wallet Provider and represents the `client_id` of the Wallet instance. For privacy reasons, this value is the same across Wallet instances of that Wallet Provider, see (#walletattestation-sub) for more details. +# Proof Types {#proof-types} + +A proof type communicates a proof of cryptographic key material used for binding a Credential in the Credential Request. + +This specification defines the following proof types: + +* `jwt`: A JWT [@!RFC7519] is used for proof of possession. When a `proofs` object is using a `jwt` proof type, it MUST include a `jwt` parameter with its value being a non-empty array of JWTs, where each JWT is formed as defined in (#jwt-proof-type). +* `ldp_vp`: A W3C Verifiable Presentation object signed using the Data Integrity Proof [@VC_Data_Integrity] as defined in [@VC_DATA_2.0] or [@VC_DATA] is used for proof of possession. When a `proofs` object is using a `ldp_vp` proof type, it MUST include an `ldp_vp` parameter with its value being a non-empty array of [W3C Verifiable Presentations](https://www.w3.org/TR/vc-data-model-2.0/#presentations-0), where each of these W3C Verifiable Presentation is formed as defined in (#ldp-vp-proof-type). +* `attestation`: A JWT [@!RFC7519] representing a key attestation without using a proof of possession of the cryptographic key material that is being attested. When a `proofs` object is using an `attestation` proof type, the object MUST include an `attestation` parameter with its value being an array that contains exactly one JWT that is formed as defined in (#keyattestation-jwt). + +There are two ways to convey key attestations (as defined in (#keyattestation)) of the cryptographic key material during Credential issuance: + +- The Wallet uses the `jwt` proof type in the Credential Request to create a proof of possession of the key and adds the key attestation in the JOSE header. +- The Wallet uses the `attestation` proof type in the Credential Request with the key attestation without a proof of possession of the key itself. + +Depending on the Wallet's implementation, the `attestation` may avoid unnecessary End-User interaction during Credential issuance, as the key itself does not necessarily need to perform signature operations. + +Additional proof types MAY be defined and used. + +## `jwt` Proof Type {#jwt-proof-type} + +The JWT MUST contain the following elements: + +* in the JOSE header, + * `alg`: REQUIRED. A digital signature algorithm identifier such as per IANA "JSON Web Signature and Encryption Algorithms" registry [@IANA.JOSE]. It MUST NOT be `none` or an identifier for a symmetric algorithm (MAC). + * `typ`: REQUIRED. MUST be `openid4vci-proof+jwt`, which explicitly types the key proof JWT as recommended in Section 3.11 of [@!RFC8725]. + * `kid`: OPTIONAL. JOSE Header containing the key ID. If the Credential shall be bound to a DID, the `kid` refers to a DID URL which identifies a particular key in the DID Document that the Credential shall be bound to. It MUST NOT be present if `jwk` is present. + * `jwk`: OPTIONAL. JOSE Header containing the key material the new Credential shall be bound to. It MUST NOT be present if `kid` is present. + * `x5c`: OPTIONAL. JOSE Header containing a certificate or certificate chain corresponding to the key used to sign the JWT. + * `key_attestation`: OPTIONAL. JOSE Header containing a key attestation as described in (#keyattestation). + * `trust_chain`: OPTIONAL. JOSE Header containing an [@!OpenID.Federation] Trust Chain. This element MAY be used to convey key attestation, metadata, metadata policies, federation Trust Marks and any other information related to a specific federation, if available in the chain. When used for signature verification, the header parameter `kid` MUST be present. + +* in the JWT body, + * `iss`: OPTIONAL (string). The value of this claim MUST be the `client_id` of the Client making the Credential request. This claim MUST be omitted if the access token authorizing the issuance call was obtained from a Pre-Authorized Code Flow through anonymous access to the token endpoint. + * `aud`: REQUIRED (string). The value of this claim MUST be the Credential Issuer Identifier. + * `iat`: REQUIRED (number). The value of this claim MUST be the time at which the key proof was issued using the syntax defined in [@!RFC7519]. + * `nonce`: OPTIONAL (string). The value type of this claim MUST be a string, where the value is a server-provided `c_nonce`. It MUST be present when the Wallet received a server-provided `c_nonce`. + +The Credential Issuer MUST validate that the JWT used as a proof is actually signed by a key identified in the JOSE Header. + +The Credential Issuer SHOULD issue a Credential for each cryptographic public key specified in the `attested_keys` claim within the `key_attestation` parameter. + +Cryptographic algorithm names used in the `proof_signing_alg_values_supported` Credential Issuer metadata parameter for this proof type SHOULD be one of those defined in [@IANA.JOSE]. + +Below is a non-normative example of a `proofs` parameter (with line breaks within values for display purposes only): + +```json +{ + "jwt": [ + "eyJ0eXAiOiJvcGVuaWQ0dmNpLXByb29mK2p3dCIsImFsZyI6IkVTMjU2Iiwiand + rIjp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ4IjoiblVXQW9BdjNYWml0aDh + FN2kxOU9kYXhPTFlGT3dNLVoyRXVNMDJUaXJUNCIsInkiOiJIc2tIVThCalVpMVU + 5WHFpN1N3bWo4Z3dBS18weGtjRGpFV183MVNvc0VZIn19.eyJhdWQiOiJodHRwcz + ovL2NyZWRlbnRpYWwtaXNzdWVyLmV4YW1wbGUuY29tIiwiaWF0IjoxNzAxOTYwND + Q0LCJub25jZSI6IkxhclJHU2JtVVBZdFJZTzZCUTR5bjgifQ.-a3EDsxClUB4O3L + eDD5DVGEnNMT01FCQW4P6-2-BNBqc_Zxf0Qw4CWayLEpqkAomlkLb9zioZoipdP- + jvh1WlA" + ] +} +``` + +where the decoded JWT looks like this: + +```json +{ + "typ": "openid4vci-proof+jwt", + "alg": "ES256", + "jwk": { + "kty": "EC", + "crv": "P-256", + "x": "nUWAoAv3XZith8E7i19OdaxOLYFOwM-Z2EuM02TirT4", + "y": "HskHU8BjUi1U9Xqi7Swmj8gwAK_0xkcDjEW_71SosEY" + } +}.{ + "aud": "https://credential-issuer.example.com", + "iat": 1701960444, + "nonce": "LarRGSbmUPYtRYO6BQ4yn8" +} +``` + +Here is another example JWT not only proving possession of a private key but also providing key attestation data for that key: + +```json +{ + "typ": "openid4vci-proof+jwt", + "alg": "ES256", + "kid": "0", + "key_attestation": +}. +{ + "iss": "s6BhdRkqt3", + "aud": "https://server.example.com", + "iat": 1659145924, + "nonce": "tZignsnFbp" +} +``` + +## `ldp_vp` Proof Type {#ldp-vp-proof-type} + +When a W3C Verifiable Presentation as defined by [@VC_DATA_2.0] or [@VC_DATA] signed using Data Integrity is used as key proof, it MUST contain the following elements: + +* `holder`: OPTIONAL. MUST be equivalent to the controller identifier (e.g., DID) for the `verificationMethod` value identified by the `proof.verificationMethod` property. +* `proof`: REQUIRED. The proof body of a W3C Verifiable Presentation. + * `domain`: REQUIRED (string). The value of this claim MUST be the Credential Issuer Identifier. + * `challenge`: REQUIRED when the Credential Issuer has provided a `c_nonce`. It MUST NOT be used otherwise. String, where the value is a server-provided `c_nonce`. It MUST be present when the Wallet received a server-provided `c_nonce`. + +The Credential Issuer MUST validate that the W3C Verifiable Presentation used as a proof is actually signed with a key in the possession of the Holder. + +Cryptographic algorithm names used in the `proof_signing_alg_values_supported` Credential Issuer metadata parameter for this proof type SHOULD be one of those defined in [@LD_Suite_Registry]. + +Below is a non-normative example of a `proofs` parameter: + +```json +{ + "ldp_vp": [ + { + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://www.w3.org/ns/credentials/examples/v2" + ], + "type": [ + "VerifiablePresentation" + ], + "holder": "did:key:z6MkvrFpBNCoYewiaeBLgjUDvLxUtnK5R6mqh5XPvLsrPsro", + "proof": [ + { + "type": "DataIntegrityProof", + "cryptosuite": "eddsa-2022", + "proofPurpose": "authentication", + "verificationMethod": "did:key:z6MkvrFpBNCoYewiaeBLgjUDvLxUtnK5R6mqh5XPvLsrPsro#z6MkvrFpBNCoYewiaeBLgjUDvLxUtnK5R6mqh5XPvLsrPsro", + "created": "2023-03-01T14:56:29.280619Z", + "challenge": "82d4cb36-11f6-4273-b9c6-df1ac0ff17e9", + "domain": "did:web:audience.company.com", + "proofValue": "z5hrbHzZiqXHNpLq6i7zePEUcUzEbZKmWfNQzXcUXUrqF7bykQ7ACiWFyZdT2HcptF1zd1t7NhfQSdqrbPEjZceg7" + } + ] + } + ] +} + +``` + +## `attestation` Proof Type {#attestation-proof-type} + +A key attestation in JWT format as defined in (#keyattestation-jwt). + +When a key attestation is used as a proof type, it MUST contain the `c_nonce` value provided by the Credential Issuer in its `nonce` parameter. + +Below is a non-normative example of a `proofs` parameter (with line breaks within values for display purposes only): + +```json +{ + "attestation": [ + "" + ] +} +``` + +The Credential Issuer SHOULD issue a Credential for each cryptographic public key specified in the `attested_keys` claim within the `key_attestation` parameter. + +## Verifying Proof {#verifying-key-proof} + +To validate a key proof, the Credential Issuer MUST ensure that: + +- all required claims for that proof type are contained as defined in (#proof-types), +- the key proof is explicitly typed using header parameters as defined for that proof type, +- the header parameter indicates a registered asymmetric digital signature algorithm, `alg` parameter value is not `none`, is supported by the application, and is acceptable per local policy, +- the signature on the key proof verifies with the public key contained in the header parameter, +- the header parameter does not contain a private key, +- if the server had previously provided a `c_nonce`, the nonce in the key proof matches the server-provided `c_nonce` value, +- the creation time of the JWT, as determined by either the issuance time, or a server managed timestamp via the nonce claim, is within an acceptable window (see (#key-proof-replay)). + +These checks may be performed in any order. + # IANA Considerations ## OAuth URI Registry @@ -2750,6 +2749,7 @@ The technology described in this specification was made available from contribut -16 + * move proof type section to the Annex for readability, add some introduction and fix text in Section 8.1 * Adds an option to return DPoP Nonce from the Nonce Endpoint * Change Cryptographic Holder Binding to Cryptographic Key Binding * add privacy considerations for the client_id used with wallet attestations