diff --git a/examples/query_lang/claims_alternatives.json b/examples/query_lang/claims_alternatives.json new file mode 100644 index 0000000..36ac221 --- /dev/null +++ b/examples/query_lang/claims_alternatives.json @@ -0,0 +1,22 @@ +{ + "credentials": [ + { + "id": "pid", + "format": "vc+sd-jwt", + "meta": { + "vct_values": [ "https://credentials.example.com/identity_credential" ] + }, + "claims": [ + {"id": "a", "path": ["last_name"]}, + {"id": "b", "path": ["postal_code"]}, + {"id": "c", "path": ["locality"]}, + {"id": "d", "path": ["region"]}, + {"id": "e", "path": ["date_of_birth"]} + ], + "claim_sets": [ + ["a", "c", "d", "e"], + ["a", "b", "e"] + ] + } + ] +} \ No newline at end of file diff --git a/examples/query_lang/complex_mdoc.json b/examples/query_lang/complex_mdoc.json new file mode 100644 index 0000000..dd13bb3 --- /dev/null +++ b/examples/query_lang/complex_mdoc.json @@ -0,0 +1,107 @@ +{ + "credentials": [ + { + "id": "mdl-id", + "format": "mso_mdoc", + "meta": { + "doctype_value": "org.iso.18013.5.1.mDL" + }, + "claims": [ + { + "id": "given_name", + "namespace": "org.iso.18013.5.1", + "claim_name": "given_name" + }, + { + "id": "family_name", + "namespace": "org.iso.18013.5.1", + "claim_name": "family_name" + }, + { + "id": "portrait", + "namespace": "org.iso.18013.5.1", + "claim_name": "portrait" + } + ] + }, + { + "id": "mdl-address", + "format": "mso_mdoc", + "meta": { + "doctype_value": "org.iso.18013.5.1.mDL" + }, + "claims": [ + { + "id": "resident_address", + "namespace": "org.iso.18013.5.1", + "claim_name": "resident_address" + }, + { + "id": "resident_country", + "namespace": "org.iso.18013.5.1", + "claim_name": "resident_country" + } + ] + }, + { + "id": "photo_card-id", + "format": "mso_mdoc", + "meta": { + "doctype_value": "org.iso.23220.photoid.1" + }, + "claims": [ + { + "id": "given_name", + "namespace": "org.iso.23220.1", + "claim_name": "given_name" + }, + { + "id": "family_name", + "namespace": "org.iso.23220.1", + "claim_name": "family_name" + }, + { + "id": "portrait", + "namespace": "org.iso.23220.1", + "claim_name": "portrait" + } + ] + }, + { + "id": "photo_card-address", + "format": "mso_mdoc", + "meta": { + "doctype_value": "org.iso.23220.photoid.1" + }, + "claims": [ + { + "id": "resident_address", + "namespace": "org.iso.23220.1", + "claim_name": "resident_address" + }, + { + "id": "resident_country", + "namespace": "org.iso.23220.1", + "claim_name": "resident_country" + } + ] + } + ], + "credential_sets": [ + { + "purpose": "Identification", + "options": [ + [ "mdl-id" ], + [ "photo_card-id" ] + ] + }, + { + "purpose": "Proof of address", + "required": false, + "options": [ + [ "mdl-address" ], + [ "photo_card-address" ] + ] + } + ] +} \ No newline at end of file diff --git a/examples/query_lang/credentials_alternatives.json b/examples/query_lang/credentials_alternatives.json new file mode 100644 index 0000000..cdbec8d --- /dev/null +++ b/examples/query_lang/credentials_alternatives.json @@ -0,0 +1,78 @@ +{ + "credentials": [ + { + "id": "pid", + "format": "vc+sd-jwt", + "meta": { + "vct_values": ["https://credentials.example.com/identity_credential"] + }, + "claims": [ + {"path": ["given_name"]}, + {"path": ["family_name"]}, + {"path": ["address", "street_address"]} + ] + }, + { + "id": "other_pid", + "format": "vc+sd-jwt", + "meta": { + "vct_values": ["https://othercredentials.example/pid"] + }, + "claims": [ + {"path": ["given_name"]}, + {"path": ["family_name"]}, + {"path": ["address", "street_address"]} + ] + }, + { + "id": "pid_reduced_cred_1", + "format": "vc+sd-jwt", + "meta": { + "vct_values": ["https://credentials.example.com/reduced_identity_credential"] + }, + "claims": [ + {"path": ["family_name"]}, + {"path": ["given_name"]} + ] + }, + { + "id": "pid_reduced_cred_2", + "format": "vc+sd-jwt", + "meta": { + "vct_values": ["https://cred.example/residence_credential"] + }, + "claims": [ + {"path": ["postal_code"]}, + {"path": ["locality"]}, + {"path": ["region"]} + ] + }, + { + "id": "nice_to_have", + "format": "vc+sd-jwt", + "meta": { + "vct_values": ["https://company.example/company_rewards"] + }, + "claims": [ + {"path": ["rewards_number"]} + ] + } + ], + "credential_sets": [ + { + "purpose": "Identification", + "options": [ + [ "pid" ], + [ "other_pid" ], + [ "pid_reduced_cred_1", "pid_reduced_cred_2" ] + ] + }, + { + "purpose": "Show your rewards card", + "required": false, + "options": [ + [ "nice_to_have" ] + ] + } + ] +} \ No newline at end of file diff --git a/examples/query_lang/multi_credentials.json b/examples/query_lang/multi_credentials.json new file mode 100644 index 0000000..b62b25e --- /dev/null +++ b/examples/query_lang/multi_credentials.json @@ -0,0 +1,33 @@ +{ + "credentials": [ + { + "id": "pid", + "format": "vc+sd-jwt", + "meta": { + "vct_values": ["https://credentials.example.com/identity_credential"] + }, + "claims": [ + {"path": ["given_name"]}, + {"path": ["family_name"]}, + {"path": ["address", "street_address"]} + ] + }, + { + "id": "mdl", + "format": "mso_mdoc", + "meta": { + "doctype_value": "org.iso.7367.1.mVRC" + }, + "claims": [ + { + "namespace": "org.iso.7367.1", + "claim_name": "vehicle_holder" + }, + { + "namespace": "org.iso.18013.5.1", + "claim_name": "first_name" + } + ] + } +] +} \ No newline at end of file diff --git a/examples/query_lang/simple.json b/examples/query_lang/simple.json new file mode 100644 index 0000000..8c0a00e --- /dev/null +++ b/examples/query_lang/simple.json @@ -0,0 +1,16 @@ +{ + "credentials": [ + { + "id": "my_credential", + "format": "vc+sd-jwt", + "meta": { + "vct_values": [ "https://credentials.example.com/identity_credential" ] + }, + "claims": [ + {"path": ["last_name"]}, + {"path": ["first_name"]}, + {"path": ["address", "street_address"]} + ] + } + ] +} \ No newline at end of file diff --git a/examples/query_lang/simple_mdoc.json b/examples/query_lang/simple_mdoc.json new file mode 100644 index 0000000..aa46d30 --- /dev/null +++ b/examples/query_lang/simple_mdoc.json @@ -0,0 +1,21 @@ +{ + "credentials": [ + { + "id": "my_credential", + "format": "mso_mdoc", + "meta": { + "doctype_value": "org.iso.7367.1.mVRC" + }, + "claims": [ + { + "namespace": "org.iso.7367.1", + "claim_name": "vehicle_holder" + }, + { + "namespace": "org.iso.18013.5.1", + "claim_name": "first_name" + } + ] + } + ] +} \ No newline at end of file diff --git a/examples/query_lang/value_matching_simple.json b/examples/query_lang/value_matching_simple.json new file mode 100644 index 0000000..b4d26f3 --- /dev/null +++ b/examples/query_lang/value_matching_simple.json @@ -0,0 +1,23 @@ +{ + "credentials": [ + { + "id": "my_credential", + "format": "vc+sd-jwt", + "meta": { + "vct_values": [ "https://credentials.example.com/identity_credential" ] + }, + "claims": [ + { + "path": ["last_name"], + "values": ["Doe"] + }, + {"path": ["first_name"]}, + {"path": ["address", "street_address"]}, + { + "path": ["postal_code"], + "values": ["90210", "90211"] + } + ] + } + ] +} \ No newline at end of file diff --git a/openid-4-verifiable-presentations-1_0.md b/openid-4-verifiable-presentations-1_0.md index a0ff6dd..5dcac41 100644 --- a/openid-4-verifiable-presentations-1_0.md +++ b/openid-4-verifiable-presentations-1_0.md @@ -113,7 +113,7 @@ Biometrics-based Holder Binding: : Ability of the Holder to prove legitimate possession of a Verifiable Credential by demonstrating a certain biometric trait, such as finger print or face. One example of a Verifiable Credential with biometric Holder Binding is a mobile driving license [@ISO.18013-5], which contains a portrait of the Holder. VP Token: -: An artifact defined in this specification that contains a single Verifiable Presentation or an array of Verifiable Presentations as defined in (#response-parameters). +: An artifact containing one or more Verifiable Presentations returned as a response to an Authorization Request. The structure of VP Tokens is defined in (#response-parameters). Wallet: : An entity used by the Holder to receive, store, present, and manage Verifiable Credentials and key material. There is no single deployment model of a Wallet: Verifiable Credentials and keys can both be stored/managed locally, or by using a remote self-hosted service, or a remote third-party service. In the context of this specification, the Wallet acts as an OAuth 2.0 Authorization Server (see [@!RFC6749]) towards the Credential Verifier which acts as the OAuth 2.0 Client. @@ -222,6 +222,8 @@ Figure: Cross Device Flow OpenID for Verifiable Presentations extends existing OAuth 2.0 mechanisms as following: * A new `presentation_definition` Authorization Request parameter that uses the [@!DIF.PresentationExchange] syntax is defined to request presentation of Verifiable Credentials in arbitrary formats. See (#vp_token_request) for more details. +* A new query language, the Digital Credentials Query Language (DCQL), is defined to enable requesting Verifiable Credentials in an easier and more flexible way. See (#dcql_query) for more details. +* A new `dcql_query` Authorization Request parameter is defined to request presentation of Verifiable Credentials in the JSON-encoded DCQL format. See (#vp_token_request) for more details. * A new `vp_token` response parameter is defined to return Verifiable Presentations to the Verifier in either Authorization or Token Response depending on the Response Type. See (#response) for more details. * New Response Types `vp_token` and `vp_token id_token` are defined to request Verifiable Credentials to be returned in the Authorization Response (standalone or along with a Self-Issued ID Token [@!SIOPv2]). See (#response) for more details. * A new OAuth 2.0 Response Mode `direct_post` is defined to support sending the response across devices, or when the size of the response exceeds the redirect URL character size limitation. See (#response_mode_post) for more details. @@ -259,10 +261,15 @@ One exception to this rule is `transaction_data` parameter, and the wallets that This specification defines the following new request parameters: `presentation_definition`: -: A string containing a Presentation Definition JSON object. See (#request_presentation_definition) for more details. This parameter MUST be present when `presentation_definition_uri` parameter, or a `scope` value representing a Presentation Definition is not present. +: A string containing a Presentation Definition JSON object. See (#request_presentation_definition) for more details. `presentation_definition_uri`: -: A string containing an HTTPS URL pointing to a resource where a Presentation Definition JSON object can be retrieved. This parameter MUST be present when `presentation_definition` parameter, or a `scope` value representing a Presentation Definition is not present. See (#request_presentation_definition_uri) for more details. +: A string containing an HTTPS URL pointing to a resource where a Presentation Definition JSON object can be retrieved. See (#request_presentation_definition_uri) for more details. + +`dcql_query`: +: A string containing a JSON-encoded DCQL query as defined in (#dcql_query). + +Exactly one of the following parameters MUST be present in the Authorization Request: `dcql_query`, `presentation_definition`, `presentation_definition_uri`, or a `scope` value representing a Presentation Definition. `client_metadata`: : OPTIONAL. A JSON object containing the Verifier metadata values. It MUST be UTF-8 encoded. The following metadata parameters MAY be used: @@ -419,17 +426,18 @@ Content-Type: application/json Wallets MAY support requesting presentation of Verifiable Credentials using OAuth 2.0 scope values. -Such a scope value MUST be an alias for a well-defined Presentation Definition that will be -referred to in the `presentation_submission` response parameter. +Such a scope value MUST be an alias for +- a well-defined DCQL query, or +- a well-defined Presentation Definition (for Presentation Exchange) that will be referred to in the `presentation_submission` response parameter. The specific scope values, and the mapping between a certain scope value and the respective -Presentation Definition is out of scope of this specification. +DCQL query or Presentation Definition is out of scope of this specification. Possible options include normative text in a separate specification defining scope values along with a description of their -semantics or machine readable definitions in the Wallet's server metadata, mapping a scope value to an equivalent +semantics or machine-readable definitions in the Wallet's server metadata, mapping a scope value to an equivalent Presentation Definition JSON object. -Such definition of a scope value MUST allow the Verifier to determine the identifiers of the Presentation Definition and Input Descriptor(s) in the `presentation_submission` response parameter (`definition_id` and `descriptor_map.id` respectively) as well as the Credential formats and types in the `vp_token` response parameter defined in (#response-parameters). +If Presentation Exchange is used, the definition of the scope value MUST allow the Verifier to determine the identifiers of the Presentation Definition and Input Descriptor(s) in the `presentation_submission` response parameter (`definition_id` and `descriptor_map.id` respectively) as well as the Credential formats and types in the `vp_token` response parameter defined in (#response-parameters). It is RECOMMENDED to use collision-resistant scopes values. @@ -616,11 +624,325 @@ The Wallet then validates the request as specified in OAuth 2.0 [@RFC6749]. If the Verifier responds with any HTTP error response, the Wallet MUST terminate the process. +# Digital Credentials Query Language (DCQL) {#dcql_query} + +The Digital Credentials Query Language (DCQL, pronounced [ˈdakl̩]) is a +JSON-encoded query language that allows the Verifier to request Verifiable +Presentations that match the query. The Verifier MAY encode constraints on the +combinations of credentials and claims that are requested. The Wallet evaluates +the query against the Verifiable Credentials it holds and returns Verifiable +Presentations matching the query. + +A valid DCQL query is defined as a JSON-encoded object with the following +top-level properties: + +`credentials`: +: REQUIRED. A non-empty array of Credential Queries as defined in (#credential_query) +that specify the requested Verifiable Credentials. + +`credential_sets`: +: OPTIONAL. A non-empty array of credential set queries as defined in (#credential_set_query) +that specifies additional constraints on which of the requested Verifiable Credentials to return. + +Note: Future extensions may define additional properties both on the top level +and in the rest of the DCQL data structure. Implementations MUST ignore any +unknown properties. + +## Credential Query {#credential_query} + +A Credential Query is an object representing a request for a presentation of one +Credential. + +Each entry in `credentials` MUST be an object with the following properties: + +`id`: +: REQUIRED. A string identifying the Credential in the response and, if provided, +the constraints in `credential_sets`. The value MUST be a non-empty string +consisting of alphanumeric, underscore (`_`) or hyphen (`-`) characters. +Within the Authorization Request, the same `id` MUST NOT +be present more than once. + +`format`: +: REQUIRED. A string that specifies the format of the requested +Verifiable Credential. Valid Credential Format Identifier values are defined in +Appendix A of [@!OpenID.VCI]. + +`meta`: +: OPTIONAL. An object defining additional properties requested by the Verifier that +apply to the metadata and validity data of the Credential. The properties of +this object are defined per Credential Format in (#format_specific_properties). If omitted, +no specific constraints are placed on the metadata or validity of the requested +Credential. + +`claims`: +: OPTIONAL. A non-empty array of objects as defined in (#claims_query) that specifies +claims in the requested Credential. + +`claim_sets`: +: OPTIONAL. A non-empty array containing arrays of identifiers for +elements in `claims` that specifies which combinations of `claims` for the Credential are requested. +The rules for selecting claims to send are defined in (#selecting_claims). + +Note that multiple Credential Queries in a request MAY request a presentation of the same Credential. + +## Credential Set Query {#credential_set_query} + +A Credential Set Query is an object representing a request for one or more credentials to satisfy +a particular use case with the Verifier. + +Each entry in `credential_sets` MUST be an object with the following properties: + +`options` +: REQUIRED: A non-empty array, where each value in the array is a list +of Credential Query identifiers representing one set of Credentials that +satisfies the use case. The value of each element in the `options` array is an +array of identifiers which reference elements in `credentials`. + +`required` +: OPTIONAL. A boolean which indicates whether this set of Credentials is required +to satisfy the particular use case at the Verifier. If omitted, the default value is `true`. + +`purpose` +: OPTIONAL. A string, number or object specifying the purpose of the +query. This specification does not define a specific structure or specific values +for this property. The purpose is intended to be used by the Verifier to +communicate the reason for the query to the Wallet. The Wallet MAY use this +information to show the user the reason for the request. + +## Claims Query {#claims_query} + +Each entry in `claims` MUST be an object with the following properties: + +`id`: +: REQUIRED if `claim_sets` is present in the Credential Query; OPTIONAL otherwise. A string +identifying the particular claim. The value MUST be a non-empty string +consisting of alphanumeric, underscore (`_`) or hyphen (`-`) characters. +Within the particular `claims` array, the same `id` MUST NOT +be present more than once. + +`path`: +: REQUIRED if the Credential Format uses a JSON-based claims structure; MUST NOT +be present otherwise. The value MUST be a non-empty array representing a claims path pointer that specifies the path to a claim +within the Verifiable Credential, as defined in (#claims_path_pointer). + +`namespace`: +: REQUIRED if the Credential Format is based on the mdoc format defined in ISO 18013-5; MUST NOT be present otherwise. +The value MUST be a string that specifies the namespace of the data element +within the mdoc, e.g., `org.iso.18013.5.1`. + +`claim_name`: +: REQUIRED if the Credential Format is based on mdoc format defined in ISO 18013-5; MUST NOT be present otherwise. +The value MUST be a string that specifies the data element identifier of the data element within the provided namespace +in the mdoc, e.g., `first_name`. + +`values`: +: OPTIONAL. An array of strings, integers or boolean values that specifies the expected values of the claim. +If the `values` property is present, the Wallet SHOULD return the claim only if the +type and value of the claim both match for at least one of the elements in the array. Details of the processing rules are defined in (#selecting_claims). + +### Selecting Claims and Credentials {#dcql_query_lang_processing_rules} + +The following section describes the logic that applies for selecting claims +and for selecting credentials. + +#### Selecting Claims {#selecting_claims} + +The following rules apply for selecting claims via `claims` and `claim_sets`: + +- If `claims` is absent, the Verifier requests all claims existing + in the Credential. +- If `claims` is present, but `claim_sets` is absent, + the Verifier requests all claims listed in `claims`. +- If both `claims` and `claim_sets` are present, the Verifier requests one combination of the claims listed in + `claim_sets`. The order of the options conveyed in the `claim_sets` + array expresses the Verifier's preference for what is returned; the Wallet MUST return + the first option that it can satisfy. If the Wallet cannot satisfy any of the + options, it MUST NOT return any claims. + +When a Claims Query contains a restriction on the values of a claim, the Wallet +SHOULD NOT return the claim if its value does not match at least one of the +elements in `values` i.e., the claim should be treated the same as if it did not +exist in the Credential. Implementing this restriction may not be possible in +all cases, for example, if the Wallet does not have access to the claim value +before presentation or user consent or if another component routing +the request to the Wallet does not have access to the claim value. Therefore, Verifiers +must treat restrictions expressed using `values` as a best-effort way to improve +user privacy, but MUST NOT rely on it for security checks. + +The purpose of the `claim_sets` syntax is to provide a way for a verifier to +describe alternative ways a given credential can satisfy the request. The array +ordering expresses the Verifier's preference for how to fulfill the request. The +first element in the array is the most preferred and the last element in the +array is the least preferred. Verifiers SHOULD use the principle of least +information disclosure to influence how they order these options. For example, a +proof of age request should prioritize requesting an attribute like +`age_over_18` over an attribute like `birth_date`. The `claim_sets` syntax is +not intended to define options the user can choose from, see (#dcql_query_ui) for +more information. + +If the Wallet cannot deliver all claims requested by the Verifier +according to these rules, it MUST NOT return the respective Credential. + +#### Selecting Credentials + +The following rules apply for selecting Credentials via `credentials` and `credential_sets`: + +- If `credential_sets` is not provided, the Verifier requests presentations for all + Credentials in `credentials` to be returned. +- Otherwise, the Verifier requests presentations of Credentials to be returned satisfying + - all of the Credential Set Queries in the `credential_sets` array where the `required` attribute is true or omitted, and + - optionally, any of the other Credential Set Queries. + +To satisfy a Credential Set Query, the Wallet MUST return presentations of a +set of Credentials that match to one of the `options` inside the +Credential Set Query. + +Credentials not matching the respective constraints expressed within +`credentials` MUST NOT be returned, i.e., they are treated as if +they would not exist in the Wallet. + +If the Wallet cannot deliver all non-optional Credentials requested by the +Verifier according to these rules, it MUST NOT return any Credential(s). + +#### User Interface Considerations {#dcql_query_ui} + +While this specification provides the mechanisms for requesting different sets +of claims and Credentials, it does not define details about the user interface +of the Wallet, for example, if and how users can select which combination of +Credentials to present. However, it is typically expected that the Wallet +presents the End-User with a choice of which Credential(s) to present if +multiple of the sets of Credentials in `options` can satisfy the request. + +#### Security Considerations {#dcql_query_security} + +While the Verifier can specify various constraints both on the claims level and +the Credential level as shown above, it MUST NOT rely on the Wallet to enforce +these constraints. The Wallet is not controlled by the Verifier and the Verifier +MUST perform its own security checks on the returned Credentials and +presentations. + +## Format-specific Properties {#format_specific_properties} + +OpenID for Verifiable Presentations is Credential Format agnostic, i.e., it is designed to allow applications to request and receive Verifiable Presentations and Verifiable Credentials in any Credential Format. This section defines Credential Format Profiles for some of the known Credential Formats. Other specifications or deployments can define their own Credential Format Profiles: + +### IETF SD-JWT VC {#format_vc_sd_jwt} + +`vct_values`: +: OPTIONAL. An array of strings that specifies allowed values for +the type of the requested Verifiable Credential. All elements in the array MUST +be valid type identifiers as defined in [@!I-D.ietf-oauth-sd-jwt-vc]. The Wallet +MAY return credentials that inherit from any of the specified types, following +the inheritance logic defined in [@!I-D.ietf-oauth-sd-jwt-vc]. + +### Mobile Documents or mdocs (ISO/IEC 18013 and ISO/IEC 23220 series) {#format_mso_mdoc} + +`doctype_value`: +: OPTIONAL. String that specifies an allowed value for the +doctype of the requested Verifiable Credential. It MUST +be a valid doctype identifier as defined in [@ISO.18013-5]. + + +## Claims Path Pointer {#claims_path_pointer} + +A claims path pointer is a pointer into the JSON structure of the Verifiable +Credential, identifying one or more claims. A claims path pointer MUST be a +non-empty array of strings and non-negative integers. A string value +indicates that the respective key is to be selected, a null value +indicates that all elements of the currently selected array(s) are to be selected; +and a non-negative integer indicates that the respective index in an array is to be selected. The path +is formed as follows: + +Start with an empty array and repeat the following until the full path is formed. + + - To address a particular claim within an object, append the key (claim name) + to the array. + - To address an element within an array, append the index to the array (as a + non-negative, 0-based integer). + - To address all elements within an array, append a null value to the array. + +Verifiers MUST NOT point to the same claim more than once in a single query. +Wallets SHOULD ignore such duplicate claim queries. + +### Processing + +In detail, the array is processed by the Wallet from left to right as follows: + + 1. Select the root element of the Credential, i.e., the top-level JSON object. + 2. Process the query of the claims path pointer array from left to right: + 1. If the component is a string, select the element in the respective + key in the currently selected element(s). If any of the currently + selected element(s) is not an object, abort processing and return an + error. If the key does not exist in any element currently selected, + remove that element from the selection. + 2. If the component is null, select all elements of the currently + selected array(s). If any of the currently selected element(s) is not an + array, abort processing and return an error. + 3. If the component is a non-negative integer, select the element at + the respective index in the currently selected array(s). If any of the + currently selected element(s) is not an array, abort processing and + return an error. If the index does not exist in a selected array, remove + that array from the selection. + 3. If the set of elements currently selected is empty, abort processing and + return an error. + +The result of the processing is the set of elements which is requested for +presentation. + +### Claims Path Pointer Example {#claims_path_pointer_example} + +The following shows a non-normative, simplified example of a Credential: + +```json +{ + "name": "Arthur Dent", + "address": { + "street_address": "42 Market Street", + "locality": "Milliways", + "postal_code": "12345" + }, + "degrees": [ + { + "type": "Bachelor of Science", + "university": "University of Betelgeuse" + }, + { + "type": "Master of Science", + "university": "University of Betelgeuse" + } + ], + "nationalities": ["British", "Betelgeusian"] +} +``` + +The following shows examples of claims path pointers and the respective selected +claims: + +- `["name"]`: The claim `name` with the value `Arthur Dent` is selected. +- `["address"]`: The claim `address` with its sub-claims as the value is + selected. +- `["address", "street_address"]`: The claim `street_address` with the value `42 + Market Street` is selected. +- `["degrees", null, "type"]`: All `type` claims in the `degrees` array are + selected. +- `["nationalities", 1]`: The second nationality is selected. + +## DCQL Examples {#dcql_query_example} + +The following is a non-normative example of a DCQL query that requests a Verifiable +Credential of the format `vc+sd-jwt` with a type value of +`https://credentials.example.com/identity_credential` and the claims `last_name`, +`first_name`, and `address.street_address`: + +<{{examples/query_lang/simple.json}} + +Additional, more complex examples can be found in (#more_dcql_query_examples). + + # Response {#response} -A VP Token is only returned if the corresponding Authorization Request contained a `presentation_definition` parameter, a `presentation_definition_uri` parameter, or a `scope` parameter representing a Presentation Definition (#vp_token_request). +A VP Token is only returned if the corresponding Authorization Request contained a `dcql_query` parameter, a `presentation_definition` parameter, a `presentation_definition_uri` parameter, or a `scope` parameter representing a Presentation Definition (#vp_token_request). -VP Token can be returned in the Authorization Response or the Token Response depending on the Response Type used. See (#response_type_vp_token) for more details. +A VP Token can be returned in the Authorization Response or the Token Response depending on the Response Type used. See (#response_type_vp_token) for more details. If the Response Type value is `vp_token`, the VP Token is returned in the Authorization Response. When the Response Type value is `vp_token id_token` and the `scope` parameter contains `openid`, the VP Token is returned in the Authorization Response alongside a Self-Issued ID Token as defined in [@!SIOPv2]. @@ -640,17 +962,19 @@ The behavior with respect to the VP Token is unspecified for any other individua ## Response Parameters {#response-parameters} -When a VP Token is returned, the respective response MUST include the following parameters: +When a VP Token is returned, the respective response includes the following parameters: `vp_token`: -: REQUIRED. JSON String or JSON object that MUST contain a single Verifiable Presentation or an array of JSON Strings and JSON objects each of them containing a Verifiable Presentations. Each Verifiable Presentation MUST be represented as a JSON string (that is a base64url-encoded value) or a JSON object depending on a format as defined in Appendix A of [@!OpenID.VCI]. When a single Verifiable Presentation is returned, the array syntax MUST NOT be used. If Appendix A of [@!OpenID.VCI] defines a rule for encoding the respective Credential format in the Credential Response, this rules MUST also be followed when encoding Credentials of this format in the `vp_token` response parameter. Otherwise, this specification does not require any additional encoding when a Credential format is already represented as a JSON object or a JSON string. +: REQUIRED. The structure of this parameter depends on the query language used to request the presentations in the Authorization Request: + * If DCQL was used, this is a JSON-encoded object; the keys are the `id` values used for the Credential Queries in the DCQL query, and the values are the Verifiable Presentations that match the respective Credential Query. The Verifiable Presentations are represented as strings or objects depending on the format as defined in Appendix A of [@!OpenID.VCI]. The same rules as above apply for encoding the Verifiable Presentations. + * In case Presentation Exchange was used, it is a JSON String or JSON object that MUST contain a single Verifiable Presentation or an array of JSON Strings and JSON objects each of them containing a Verifiable Presentations. Each Verifiable Presentation MUST be represented as a JSON string (that is a base64url-encoded value) or a JSON object depending on a format as defined in Appendix A of [@!OpenID.VCI]. When a single Verifiable Presentation is returned, the array syntax MUST NOT be used. If Appendix A of [@!OpenID.VCI] defines a rule for encoding the respective Credential format in the Credential Response, this rules MUST also be followed when encoding Credentials of this format in the `vp_token` response parameter. Otherwise, this specification does not require any additional encoding when a Credential format is already represented as a JSON object or a JSON string. `presentation_submission`: -: REQUIRED. The `presentation_submission` element as defined in [@!DIF.PresentationExchange]. It contains mappings between the requested Verifiable Credentials and where to find them within the returned VP Token. This is expressed via elements in the `descriptor_map` array, known as Input Descriptor Mapping Objects. These objects contain a field called `path`, which, for this specification, MUST have the value `$` (top level root path) when only one Verifiable Presentation is contained in the VP Token, and MUST have the value `$[n]` (indexed path from root) when there are multiple Verifiable Presentations, where `n` is the index to select. Additional parameters can be defined by Credential Formats, see (#alternative_credential_formats) for details. +: REQUIRED if Presentation Exchange was used for the request; MUST NOT be used otherwise. The `presentation_submission` element as defined in [@!DIF.PresentationExchange]. It contains mappings between the requested Verifiable Credentials and where to find them within the returned VP Token. This is expressed via elements in the `descriptor_map` array, known as Input Descriptor Mapping Objects. These objects contain a field called `path`, which, for this specification, MUST have the value `$` (top level root path) when only one Verifiable Presentation is contained in the VP Token, and MUST have the value `$[n]` (indexed path from root) when there are multiple Verifiable Presentations, where `n` is the index to select. Additional parameters can be defined by Credential Formats, see (#alternative_credential_formats) for details. Other parameters, such as `state` or `code` (from [@!RFC6749]), or `id_token` (from [@!OpenID.Core]), and `iss` (from [@RFC9207]) can be included in the response as defined in the respective specifications. `state` values MUST only contain ASCII URL safe characters (uppercase and lowercase letters, decimal digits, hyphen, period, underscore, and tilde). For the implementation considerations of a `state` parameter, see (#state_management). -The `presentation_submission` element MUST be included as a separate response parameter alongside the VP token. Clients MUST ignore any `presentation_submission` element included inside a Verifiable Presentation. +If Presentation Exchange was used for the request, the `presentation_submission` element MUST be included as a separate response parameter alongside the VP token. Clients MUST ignore any `presentation_submission` element included inside a Verifiable Presentation. Including the `presentation_submission` parameter as a separate response parameter allows the Wallet to provide the Verifier with additional information about the format and structure in advance of the processing of the VP Token, and can be used even with the Credential formats that do not allow for the direct inclusion of `presentation_submission` parameters inside a Credential itself. @@ -667,11 +991,26 @@ Location: https://client.example.org/cb# &vp_token=... ``` -The following is a non-normative example of a VP Token containing a single Verifiable Presentation: +### Examples (DCQL) {#response_dcql_query} + +The following is a non-normative example of the contents of a VP Token +containing a single Verifiable Presentation in the SD-JWT VC format after a +request using DCQL like the one shown in (#dcql_query_example) (shortened for +brevity): + +```json +{ + "my_credential": "eyJhbGci...QMA" +} +``` + +### Examples (Presentation Exchange) {#response_presentation_exchange} + +The following is a non-normative example of a VP Token containing a single Verifiable Presentation after a request using Presentation Exchange: <{{examples/response/vp_token_raw_ldp_vp.json}} -The following is a non-normative example of a `presentation_submission` parameter sent alongside a VP Token in the example above. It corresponds to a second Presentation Definition example in (#request_presentation_definition): +The following is a non-normative example of a `presentation_submission` parameter sent alongside a VP Token in the example above. It corresponds to the second Presentation Definition example in (#request_presentation_definition): <{{examples/response/presentation_submission.json}} @@ -681,7 +1020,7 @@ The following is a non-normative example of a VP Token containing multiple Verif <{{examples/response/vp_token_multiple_vps.json}} -The following is a non-normative example of a `presentation_submission` parameter sent alongside a VP Token in the example above. It does not correspond to any Presentation Definition examples in this specification: +The following is a non-normative example of a `presentation_submission` parameter sent alongside a VP Token in the example above. It does not correspond to any Presentation Definition example in this specification: <{{examples/response/presentation_submission_multiple_vps.json}} @@ -808,7 +1147,7 @@ The following is a non-normative example of the payload of a JWT used in an Auth <{{examples/response/jarm_jwt_enc_only_vc_json_body.json}} -The JWT response document MUST include `vp_token` and `presentation_submission` parameters as defined in (#response-parameters). +The JWT response document MUST include the `vp_token` and, if Presentation Exchange was used in the request, the `presentation_submission` parameters as defined in (#response-parameters). The key material used for encryption and signing SHOULD be determined using existing metadata mechanisms. @@ -905,10 +1244,12 @@ This document also defines the following additional error codes and error descri Verifiers MUST validate the VP Token in the following manner: -1. Determine the number of VPs returned in the VP Token and identify in which VP which requested VC is included, using the Input Descriptor Mapping Object(s) in the Presentation Submission. +1. Validate the format of the VP Token as defined in (#response-parameters) and verify the contents depending on the language used in the Authorization Request: + 1. If DCQL was used, ensure that the set of VPs returned satisfies all required Credential Sets (and optionally other Credential Sets). + 1. If Presentation Exchange was used, determine the number of VPs returned in the VP Token and identify in which VP which requested VC is included, using the Input Descriptor Mapping Object(s) in the Presentation Submission. 1. Validate the integrity, authenticity, and Holder Binding of any Verifiable Presentation provided in the VP Token according to the rules of the respective Presentation format. See (#preventing-replay) for the checks required to prevent replay of a VP. 1. Perform the checks on the Credential(s) specific to the Credential Format (i.e., validation of the signature(s) on each VC). -1. Confirm that the returned Credential(s) meet all criteria sent in the Presentation Definition in the Authorization Request. +1. Confirm that the returned Credential(s) meet all criteria defined in the query in the Authorization Request (e.g., Claims included in the presentation). 1. Perform the checks required by the Verifier's policy based on the set of trust requirements such as trust frameworks it belongs to (i.e., revocation checks), if applicable. Note: Some of the processing rules of the Presentation Definition and the Presentation Submission are outlined in [@!DIF.PresentationExchange]. @@ -1131,7 +1472,7 @@ Figure: Reference Design for Response Mode `direct_post` (4) The Verifier then sends the Authorization Request with the `request-id` as `state` and the `nonce` value created in step (1) to the Wallet. -(5) After authenticating the End-User and getting her consent to share the request Credentials, the Wallet sends the Authorization Response with the parameters `vp_token`, `presentation_submission` and `state` to the `response_uri` of the Verifier. +(5) After authenticating the End-User and getting their consent to share the request Credentials, the Wallet sends the Authorization Response with the parameters `vp_token`, `presentation_submission` (optional) and `state` to the `response_uri` of the Verifier. (6) The Verifier's Response URI checks whether the `state` value is a valid `request-id`. If so, it stores the Authorization Response data linked to the respective `transaction-id`. It then creates a `response_code` as fresh, cryptographically random number with sufficient entropy that it also links with the respective Authorization Response data. It then returns the `redirect_uri`, which includes the `response_code` to the Wallet. @@ -1168,7 +1509,7 @@ The Verifier MUST validate every individual Verifiable Presentation in an Author The `client_id` is used to detect the presentation of Verifiable Credentials to a party other than the one intended. This allows Verifiers take appropriate action in that case, such as not accepting the Verifiable Presentation. The `nonce` value binds the Presentation to a certain authentication transaction and allows the Verifier to detect injection of a Presentation in the flow, which is especially important in the flows where the Presentation is passed through the front-channel. -Note: Different formats for Verifiable Presentations and signature/proof schemes use different ways to represent the intended audience and the session binding. Some use claims to directly represent those values, others include the values into the calculation of cryptographic proofs. There are also different naming conventions across the different formats. The format of the respective presentation is determined from the format information in the presentation submission in the Authorization Response. +Note: Different formats for Verifiable Presentations and signature/proof schemes use different ways to represent the intended audience and the session binding. Some use claims to directly represent those values, others include the values into the calculation of cryptographic proofs. There are also different naming conventions across the different formats. In case Presentation Exchange is used in the Authorization Request, the format of the respective presentation is determined from the format information in the presentation submission in the Authorization Response. If DCQL was used, the format was defined by the Verifier in the request. The following is a non-normative example of the payload of a Verifiable Presentation of a format identifier `jwt_vp_json`: @@ -1560,6 +1901,8 @@ In the event that another component is invoked instead of the Wallet, the End-Us + + OAuth Parameters @@ -1914,6 +2257,16 @@ The profile includes the following elements: * Required Wallet and Verifier Metadata parameters and their values. * Additional restrictions on Authorization Request and Authorization Response parameters to ensure compliance with ISO/IEC TS 18013-7 [@ISO.18013-7] and ISO/IEC 23220-4 [@ISO.23220-4]. For instance, to comply with ISO/IEC TS 18013-7 [@ISO.18013-7], only the same-device flow is supported, the `request_uri` Authorization Request parameter is required, and the Authorization Response has to be encrypted. +### DCQL Query and Response + +An example DCQL query using the mdoc format is shown in (#more_dcql_query_examples). The following is a non-normative example for a VP Token in the response: + +```json +{ + "my_credential": "" +} +``` + ### Presentation Request See ISO/IEC TS 18013-7 Annex B [@ISO.18013-7] and ISO/IEC 23220-4 Annex C [@ISO.23220-4] for the latest examples on how to use the `presentation_definition` parameter for requesting Credentials in the mdoc format. @@ -1984,6 +2337,13 @@ The following is a non-normative example of `client_metadata` request parameter <{{examples/client_metadata/sd_jwt_vc_verifier_metadata.json}} +### DCQL Query and Response + +A non-normative example DCQL query using the SD-JWT VC format is shown in (#dcql_query_example). +The respective response is shown in (#response_dcql_query). + +Additional examples are shown in (#more_dcql_query_examples). + ### Presentation Request The following is a non-normative example of an Authorization Request: @@ -2074,6 +2434,45 @@ The following is a non-normative example of the payload of a Self-Issued ID Toke Note: The `nonce` and `aud` are set to the `nonce` of the request and the Client Identifier of the Verifier, respectively, in the same way as for the Verifier, Verifiable Presentations to prevent replay. + +# Examples for DCQL Queries {#more_dcql_query_examples} + +The following is a non-normative example of a DCQL query that requests a Verifiable +Credential in the format `mso_mdoc` with the claims `vehicle_holder` and +`first_name`: + +<{{examples/query_lang/simple_mdoc.json}} + +The following is a non-normative example of a DCQL query that requests multiple +Verifiable Credentials; all of them must be returned: + +<{{examples/query_lang/multi_credentials.json}} + +The following shows a complex query where the Wallet is requested to deliver the +`pid` credential, or the `other_pid` credential, or both `pid_reduced_cred_1` +and `pid_reduced_cred_2`. Additionally, the `nice_to_have` credential may +optionally be delivered. + +<{{examples/query_lang/credentials_alternatives.json}} + +The following shows a query where an ID and an address are requested; either can +come from an mDL or a photoid Credential. + +<{{examples/query_lang/complex_mdoc.json}} + +The following is a non-normative example of a DCQL query that requests + +- the mandatory claims `last_name` and `date_of_birth`, and +- either the claim `postal_code`, or, if that is not available, both of the claims `locality` and `region`. + +<{{examples/query_lang/claims_alternatives.json}} + +The following example shows a query that uses the `values` constraints +to request a credential with specific values for the `last_name` and `postal_code` claims: + +<{{examples/query_lang/value_matching_simple.json}} + + # IANA Considerations ## OAuth Authorization Endpoint Response Types Registry @@ -2318,7 +2717,7 @@ The technology described in this specification was made available from contribut -22 - + * Introduced the Digital Credentials Query Language * add transaction data mechanism * remove `client_id_scheme` and turn it into a prefix of the `client_id`; this addresses a security issue with the previous solution * Clarified what can go in the `client_metadata` parameter