From 8bdee61a87c6ed0afd8244e693cbf85f1f0a6f12 Mon Sep 17 00:00:00 2001 From: Stephen Curran Date: Thu, 30 Nov 2023 16:24:16 +0000 Subject: [PATCH 1/6] Aries RFC DIDComm Remote Procedure Call (DRPC) Signed-off-by: Stephen Curran --- features/0804-didcomm-rpc/README.md | 381 ++++++++++++++++++++++++++++ 1 file changed, 381 insertions(+) create mode 100644 features/0804-didcomm-rpc/README.md diff --git a/features/0804-didcomm-rpc/README.md b/features/0804-didcomm-rpc/README.md new file mode 100644 index 000000000..3376071fc --- /dev/null +++ b/features/0804-didcomm-rpc/README.md @@ -0,0 +1,381 @@ +# 0335: DIDComm Remote Procedure Call DRPC + +- Authors: [Stephen Curran](swcurran@cloudcompass.ca) (BC Gov), [Clecio Varjao](clecio.varjao@gov.bc.ca) (BC Gov) +- Status: [PROPOSED](/README.md#proposed) +- Since: 2023-11-29 +- Status Note: An evolution of the HTTP over DIDComm protocol to enable an Agent to request an arbitrary service from a connected Agent and get a response. +- Supersedes: +- Start Date: 2023-11-29 +- Tags: [feature](/tags.md#feature), [protocol](/tags.md#protocol) + +## Summary + +The DIDComm RPC (DRPC) protocol allows a remote request-response interaction, a +Remote Procedure Call (RPC), to be carried out through a +DIDComm channel. The requesting Aries agent sends a DIDComm message to request the remote +service be invoked, and gets back the response in another DIDComm message. The +protocol enables any request to be conveyed, and the subsequent response to be +returned, with flexibility in the formats (JSON, Base64 encoded) sent and +received. Out of scope of this protocol is how the requesting agent +discovers the services available from the responding agent, and how the two +agents know about the semantics of the requests and responses. By using DIDComm +between the requesting and responding agents, the security and privacy benefits +of DIDComm are accomplished, and the generic payloads of the messages allows for +flexibility in how and where the protocol can be used. + +## Motivation + +There are several use cases that are driving the need for this protocol: + +### App Attestation + +- A mobile wallet needs to get an [app attestation] verifiable credential from + the wallet publisher. To do that, the wallet and publisher need to exchange + information specific to to the attestation process with the Google and Apple + stores. The sequence is as follows: + - The wallet decides (for some reason) it needs an App Attestation credential from its publisher. + - If not already available, a DIDComm connection between the wallet and the attestation service is created. + - The wallet uses the RPC protocol to request a nonce from the service to be used in the attestation. The service responds with the nonce. + - The wallet uses a new instance of the RPC protocol to request the attestation be performed. The service responds with the status of the attestation process. + - The service completes the business process by initiating an Issue Credential process to issue an attestation verifiable credential. + +The wallet and service are using instances of three protocols (two RPC and one +Issue Credential) to carry out a full business process. Each must have knowledge +of the full business process--there is nothing inherent in the RPC protocol +about this process, or how it is being used. The RPC protocol is included to +provide a generic request-response mechanism that alleviates the need for building +many special purpose protocols. + +[app attestation]: https://developer.apple.com/documentation/devicecheck + +### Video Verification Service + +A second example is using the RPC protocol is to implement a video verification +service that is performed prior to issuing a credential to a wallet. In this +example, the wallet communicates over DIDComm to a Credential Issuer agent that +(during verification) is a proxy to an HTTP-based video verification service. +Rather than establishing a separate, direct channel between the wallet and the +verification service, the DIDComm channel with the Issuer service is used, and +during video verification, the Issuer agent passes data between the wallet +collecting the video data and the verification service directing the process and +receiving/reviewing the data. The wallet implements the requests needed to carry +out the steps of the verification, sending to the Issuer agent the necessary +requests. The Issuer conveys the requests to the verification service and the +responses back to the mobile wallet. At the end of the process, the Issuer can +see the result of the process, and decides on next steps between it and the +mobile wallet. + +## Tutorial + +### Name and Version + +This is the DRPC protocol. It is uniquely identified by the URI: + + "https://didcomm.org/drpc/1.0" + +### Key Concepts + +> This RFC assumes that you are familiar with [DID communication]. + +[DID communication]: /concepts/0005-didcomm/README.md + +This protocol consists of a message type to carry an arbitrary request to a +responding agent, and a second message that carries the result of processing the +request back to the sender of the first message. The interpretation of the +request, how to carry out the request, the content of the response, and the +interpretation of the response, are all up to the business logic (controllers) +of the participating agents. There is no discovery of remote services offered by +agents--it is assumed that the two participants are aware of the RPC +capabilities of one another through some other means. For example, from the [App +Attestation use case](#app-attestation), functionality to carry out the app +attestation process, and the service to use is built into the mobile wallet. + +It is expected (although not required) that an Aries Framework receiving a DRPC +message will simply pass to its associated "business logic" (controller) the +request from the sender, and waiting on the controller to provide the response +content to send back to the original sender. Apart from the messaging processing +applied to all inbound and outbound messages, the Aries Framework will not +perform any of the actual processing of the request. + +### Roles + +There are two roles in the protocol `sender` and `responder`: + +- The `sender` initiates the protocol, sending a request to the `responder`. +- The `responder` carries out the request however they see fit. The `responder` + may process the request themselves, or might invoke another service to process + the request. The `responder` might be unable or unwilling to carry out the + request. +- The `responder` returns the response from the request in a message to the `sender`. + +### States + +#### Sender + +The `sender` agent goes through the following states: + +- request-sent +- abandoned +- completed + +The state transition table for the `sender` is: + +| State / Events | Send Request | Receive Response | Receive Ack | Receive Problem Report | +| -------------- | ---------------------------------- | ------------------------------ | ------------------------------ | ------------------------------- | +| *Start* | Transition to
**request-sent** | | | | +| request-sent | | Transition to
**complete** | Transition to
**complete** | Transition to
**abandoned** | +| completed | | | | | +| abandoned | | | | | + +#### Responder + +The `responder` agent goes through the following states: + +- request-received +- abandoned +- completed + +The state transition table for the `responder` is: + +| State / Events | Receive Request | Send Response | Send Ack | Send Problem Report | +| ---------------- | -------------------------------------- | ------------------------------ | ------------------------------ | ------------------------------- | +| *Start* | Transition to
**request-received** | | | | +| request-received | | Transition to
**complete** | Transition to
**complete** | Transition to
**abandoned** | +| completed | | | | | +| abandoned | | | | | + +### Messages + +The following are the messages in the DRPC protocol, including the adopted messages. + +#### Request Message + +The `request` message is sent by the `sender` to initiate the protocol. The +message contains the information necessary for the `responder` to process the +request, prepare the response, and send the response message back. It is assumed +the `sender` knows what types of requests the `responder` is prepared to receive +and process. How the `sender` and `responder` coordinate that understanding is +out of scope of this protocol. + +The `request` message items have been chosen to make putting an HTTP request +into the `request` message easy (borrowing directly from [RFC 0335 HTTP Over +DIDComm]), but an HTTP request is not required. As long as `request_type` +identifies the request being made, and the `responder` understands it, the +message can be processed. + +[RFC 0335 HTTP Over DIDComm]: /features/0335-http-over-didcomm/README.md + +```jsonc +{ + "@type": "https://didcomm.org/drpc/1.0/request", + "@id": "2a0ec6db-471d-42ed-84ee-f9544db9da4b", + "method": "", + "request": "", + "headers": [], + "body": "" +} +``` + +The items in the message are as follows: + +- `@type` -- required, must be as above +- `@id` -- required, must be as defined in [RFC 0005 DIDComm] +- `method` -- optional, can be used to indicate an HTTP operation (`GET`, `PUT`, etc.) or any other value understood by the `responder`. +- `request_type` -- **required**, an identifier indicating the type of the request. The value could be a URI, such as an HTTP URL, that the `sender` would like `responder` to resolve, or the value could be just a string understood by the `responder`. +- `headers` -- optional, a JSON array typically used for conveying HTTP headers to be used in the processing of a `request_type` that is an HTTP URL. As with all parts of this protocol, the meaning is up to the participants of an instance of the protocol. + - When used for holding headers associated with an HTTP request, each element of the array is an object with two elements: `{"name": "", "value": ""}`. +- `body` -- optional, a [Data URL] containing the data to be included with the request. + - The use of a [Data URL] provides the participants with some flexibility in sending the request data, providing a `mime-type` and giving the `sender` the option of providing [Base64 encoded] data. + - `tl;dr` A [Data URL] allows for the inline sending of a variety of data formats. It is a string in the format: + - `data:content/type;base64,`, where `content/type` is an optional type of the data, `;base64` is optional and if present indicates the data has been [Base64 encoded], followed by the data. + +[Data URL]: https://en.wikipedia.org/wiki/Data_URI_scheme +[Base64 encoded]: https://en.wikipedia.org/wiki/Base64 + +The `responder` processing an HTTP request may want to scan and account for the +HTTP headers defined by the `sender` For example, the `responder` might detect +and respect the timeout parameter provided in a keep-alive header if the request +header is a keep-alive connection. + +#### Response Message + +A `response` message is usually sent by the `responder` to following the +processing of the request to convey the output of the processing to the +`sender`. It is assumed the `sender` understands what the contents of the +`response` message means in the context of the protocol instance. How the +`sender` and `responder` coordinate that understanding is out of scope of this +protocol. In some cases the `responder` may choose to send an [Adopted +ACK](#adopted-ack) or an [Adopted Problem Report](#adopted-problem-report) +instead of the `response` message, as described below. + +The message items have been chosen to make putting the response of an HTTP +request into the `response` message easy (borrowing directly from [RFC 0335 HTTP +Over DIDComm]), but an HTTP response is not required. As long as the `sender` +understands the contents of the items, the message can be processed. + +```jsonc + +{ + "@type": "https://didcomm.org/drpc/1.0/response", + "@id": "63d6f6cf-b723-4eaf-874b-ae13f3e3e5c5", + "status": { + "code":"", + "string":"" + }, + "headers": [], + "body": "" +} +``` + +The items in the message are as follows: + +- `@type` -- required, must be as above +- `@id` -- required, must be as defined in [RFC 0005 DIDComm] +- `status` -- optional, can be used to indicate the status of an HTTP request. +- `headers` -- optional, a JSON array typically used for conveying HTTP headers from the processing of a `request` by calling an HTTP URL. As with all parts of this protocol, the meaning is up to the participants of an instance of the protocol. + - When used for holding headers associated with an HTTP request, each element of the array is an object with two elements: + - `{"name": "", "value": ""}`. +- `body` -- optional, a [Data URL] containing the data from processing the request. + - See the details about the `body` item in the [request](#request-message) + +As with all DIDComm messages that are not the first in a protocol instance, a +`~thread` decorator **MUST** be included in the `response` message. + +#### Adopted ACK + +Since all of the items in the [Response Message](#response-message) are +optional, in some cases it might be easier for a `responder` to simply respond +to a `request` with an adopted [RFC 0015 ACKs] message, indicating without +further detail that the `request` was processed successfully. + +[RFC 0015 ACKs]: /features/0015-acks/README.md) + +```jsonc + + { + "@type": "https://didcomm.org/notification/1.0/ack", + "@id": "06d474e0-20d3-4cbf-bea6-6ba7e1891240", + "status": "OK" + } + +``` + +#### Adopted Problem Report + +In some cases, a `responder` may be unwilling or unable to complete the +`request` from the `sender`. For example, if the `responder` does not understand +the `request_type`, they obviously cannot process the request. In such cases, +the `responder` **SHOULD** send a [RFC 0035 Report Problem] problem report, with +as much detail as needed. + +In other cases, the `responder` may try to process the `request` and get an +error in the processing. The `responder` has the option of sending a `response` +message with the available details of the processing error or sending a [RFC +0035 Report Problem]. For example, if the `request` was to resolve an HTTP URL, +and the HTTP `request` failed, the best response might be to send the HTTP +response that was received in a DRPC `response` messages. In other cases where +the `responder` itself processed the `request`, a problem report might be a more +useful to the `sender`. + +[RFC 0035 Report Problem]: /features/0035-report-problem/README.md + +### Constraints + +The primary constraint with this protocol is that the two parties using the +protocol must understand one another--what `request_type` to use, what to +provide in the `headers` and `body`, how to process the `request`, what the +`response` means, and so on. It is not a protocol to be used between arbitrary +parties, but rather one where the parties have knowledge outside of DIDComm of +one another and their mutual capabilities. + +On the other hand, that constrain enables great flexibility, allowing +collaborating agents to accomplish almost any request-response transaction over +DIDComm without needing to define additional DIDComm protocols. More complex +interactions can be accomplished by carrying out a sequence of DRPC protocol +instances between agents. + +The flexibility DRPC protocol allows for experimenting with interactions between +agents that could later evolve into formal DIDComm protocols designed for a +specific purpose. + +## Reference + +### Codes Catalog + +A `request_type` codes catalog *could* be developed over time and included +in this part of the RFC. This might the first step in transitioning a given +interaction implemented using DRPC into formally specified interaction. + +At this time, there are no codes to be cataloged. + +## Drawbacks + +Anything that can be done by using the DRPC protocol can be accomplished by a +formally defined protocol specific to the task to be accomplished. The advantage +of the DRPC protocol is that pairs of agent instances that are collaborating can +use the protocol to collaborate without having to first define a task-specific +protocol. + +## Rationale and alternatives + +This design builds on the experience of implementations of this kind of feature +using [RFC 0095 Basic Message] and [RFC 0335 HTTP Over DIDComm]. This design +tries to build off the learnings gained from both of those implementations. + +## Prior art + +This protocol is very similar to the [RFC 0335 HTTP Over DIDComm] protocol, +borrowing heavily from its design and concepts. The motivations for adding this protocol versus +simply using that existing protocol are as follows. + +- To enable other types of requests, beyond HTTP, to be handled using the protocol. +- To relieve the Aries Framework from any role in the execution of the protocol. + With [RFC 0335 HTTP Over DIDComm], it is possible that the Aries Framework + could handle the HTTP request/response, without engaging the business logic + (controller) of the agent. This protocol strongly recommends that the + controller handle the processing. +- Enables, when processing requests to resolve HTTP URLs, the controller to + handle any necessary authorizations with the HTTP-based service being called. +- It is not clear what role the `~purpose` item (based on [RFC 0351 Purpose + Decorator]) plays and how it should be used in the relatively simple use cases + envisioned being implemented using this protocol. + +[RFC 0351 Purpose Decorator]: /concepts/0351-purpose-decorator/README.md + +One of the example use cases for this protocol has been implemented by "hijacking" the +[RFC 0095 Basic Message] protocol to carry out the needed request/response actions. This +approach is less than ideal in that: + +- That is not the intended use of [RFC 0095 Basic Message], which is to send a + basic, human consumable, message to the other agent. +- The `request_type` and all of the parameters for the request have to be encoded into the basic message. +- The [RFC 0095 Basic Message] protocol is a single message protocols, so each + request-response interaction requires tow instances of the protocol, and for + the controllers to manage connecting the interactions together. + +[RFC 0095 Basic Message]: /features/0095-basic-message/README.md + +Since this protocol can be used in place of [RFC 0335 HTTP Over DIDComm], its +prior art comments likewise apply to the DRPC protocol: + +- VPNs and onion routing (like Tor) provide solutions for similar use cases, but none so far use DIDs, which enable more complex use cases with privacy preservation. + - TLS/HTTPS, being HTTP over TLS, provides a similar transport-layer secure channel to HTTP over DIDComm. Note, this is why this RFC doesn't specify a means to perform HTTPS over DIDComm - DIDComm serves the same role as TLS does in HTTPS, but offers additional benefits: + - Verifiable yet anonymous authentication of the client, for example, using delegated credentials. + - Access to DIDComm mechanisms, such as using the introduce protocol to connect the client and server. + +## Unresolved questions + +- Should we include the idea of a `request` having a goal code ([RFC 0519 Goal Codes])? +- Should we simply use [RFC 0335 HTTP Over DIDComm]? + +[RFC 0519 Goal Codes]: /concepts/0519-goal-codes/README.md + +## Implementations + +The following lists the implementations (if any) of this RFC. Please do a pull request to add your implementation. If the implementation is open source, include a link to the repo or to the implementation within the repo. Please be consistent in the "Name" field so that a mechanical processing of the RFCs can generate a list of all RFCs supported by an Aries implementation. + +*Implementation Notes* [may need to include a link to test results](README.md). + +Name / Link | Implementation Notes +--- | --- + | From 186b4fa1f3abb66daad7efc03600f80c8b2a4198 Mon Sep 17 00:00:00 2001 From: Stephen Curran Date: Tue, 5 Dec 2023 00:48:40 +0000 Subject: [PATCH 2/6] Applied feedback from Clecio Signed-off-by: Stephen Curran --- features/0804-didcomm-rpc/README.md | 40 ++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/features/0804-didcomm-rpc/README.md b/features/0804-didcomm-rpc/README.md index 3376071fc..295596ff4 100644 --- a/features/0804-didcomm-rpc/README.md +++ b/features/0804-didcomm-rpc/README.md @@ -1,6 +1,6 @@ -# 0335: DIDComm Remote Procedure Call DRPC +# 0804: DIDComm Remote Procedure Call (DRPC) -- Authors: [Stephen Curran](swcurran@cloudcompass.ca) (BC Gov), [Clecio Varjao](clecio.varjao@gov.bc.ca) (BC Gov) +- Authors: [Clecio Varjao](clecio.varjao@gov.bc.ca) (BC Gov), [Stephen Curran](swcurran@cloudcompass.ca) (BC Gov) - Status: [PROPOSED](/README.md#proposed) - Since: 2023-11-29 - Status Note: An evolution of the HTTP over DIDComm protocol to enable an Agent to request an arbitrary service from a connected Agent and get a response. @@ -158,7 +158,7 @@ and process. How the `sender` and `responder` coordinate that understanding is out of scope of this protocol. The `request` message items have been chosen to make putting an HTTP request -into the `request` message easy (borrowing directly from [RFC 0335 HTTP Over +into the `request` message easy (borrowing from [RFC 0335 HTTP Over DIDComm]), but an HTTP request is not required. As long as `request_type` identifies the request being made, and the `responder` understands it, the message can be processed. @@ -169,10 +169,9 @@ message can be processed. { "@type": "https://didcomm.org/drpc/1.0/request", "@id": "2a0ec6db-471d-42ed-84ee-f9544db9da4b", - "method": "", "request": "", - "headers": [], - "body": "" + "headers": [{"name": "Content-Type", "value": "application/json"}], + "body.base64": "" } ``` @@ -180,15 +179,14 @@ The items in the message are as follows: - `@type` -- required, must be as above - `@id` -- required, must be as defined in [RFC 0005 DIDComm] -- `method` -- optional, can be used to indicate an HTTP operation (`GET`, `PUT`, etc.) or any other value understood by the `responder`. - `request_type` -- **required**, an identifier indicating the type of the request. The value could be a URI, such as an HTTP URL, that the `sender` would like `responder` to resolve, or the value could be just a string understood by the `responder`. -- `headers` -- optional, a JSON array typically used for conveying HTTP headers to be used in the processing of a `request_type` that is an HTTP URL. As with all parts of this protocol, the meaning is up to the participants of an instance of the protocol. - - When used for holding headers associated with an HTTP request, each element of the array is an object with two elements: `{"name": "", "value": ""}`. -- `body` -- optional, a [Data URL] containing the data to be included with the request. - - The use of a [Data URL] provides the participants with some flexibility in sending the request data, providing a `mime-type` and giving the `sender` the option of providing [Base64 encoded] data. - - `tl;dr` A [Data URL] allows for the inline sending of a variety of data formats. It is a string in the format: - - `data:content/type;base64,`, where `content/type` is an optional type of the data, `;base64` is optional and if present indicates the data has been [Base64 encoded], followed by the data. +- `headers` -- optional, a JSON array typically used for conveying HTTP headers to be used in the processing of an HTTP URL `request_type`. As with all parts of this protocol, the meaning is up to the participants of an instance of the protocol. + - Each element of the array is an object with two elements: `{"name": "", "value": ""}`. + - When a `body` is included, a **required** element in the array is `"name": "Content-Type"` with the `"value"` being the `body`'s [MIME Type] (also know as the media type). +- `body.base64` -- optional, the [Base64 encoded] body of the request. + - When Base64 decoded, the result must be in the format defined by the `Content-Type` value in the `headers` array. +[MIME Type]: https://developer.mozilla.org/en-US/docs/Glossary/MIME_type [Data URL]: https://en.wikipedia.org/wiki/Data_URI_scheme [Base64 encoded]: https://en.wikipedia.org/wiki/Base64 @@ -222,8 +220,8 @@ understands the contents of the items, the message can be processed. "code":"", "string":"" }, - "headers": [], - "body": "" + "headers": [{"name": "Content-Type", "value": "application/json"}], + "body.base64": "" } ``` @@ -232,11 +230,13 @@ The items in the message are as follows: - `@type` -- required, must be as above - `@id` -- required, must be as defined in [RFC 0005 DIDComm] - `status` -- optional, can be used to indicate the status of an HTTP request. -- `headers` -- optional, a JSON array typically used for conveying HTTP headers from the processing of a `request` by calling an HTTP URL. As with all parts of this protocol, the meaning is up to the participants of an instance of the protocol. - - When used for holding headers associated with an HTTP request, each element of the array is an object with two elements: - - `{"name": "", "value": ""}`. -- `body` -- optional, a [Data URL] containing the data from processing the request. - - See the details about the `body` item in the [request](#request-message) +- `headers` -- optional, a JSON array typically used for conveying HTTP headers to be used in the processing of an HTTP URL `request_type`. As with all parts of this protocol, the meaning is up to the participants of an instance of the protocol. +- `headers` -- optional, a JSON array typically used for conveying HTTP headers resulting from the processing of an HTTP URL `request`. As with all parts of this protocol, the meaning is up to the participants of an instance of the protocol. + - Each element of the array is an object with two elements: `{"name": "", "value": ""}`. + - When a `body` is included, a **required** element in the array is `"name": "Content-Type"` with the `"value"` being the `body`'s [MIME Type] (also know as the media type). +- `body.base64` -- optional, the [Base64 encoded] body of the request. + - When Base64 decoded, the result must be in the format defined by the `Content-Type` value in the `headers` array. + As with all DIDComm messages that are not the first in a protocol instance, a `~thread` decorator **MUST** be included in the `response` message. From a9f532f72a463c778ff1ccfbb632c5be38db5335 Mon Sep 17 00:00:00 2001 From: Stephen Curran Date: Fri, 8 Dec 2023 20:37:04 +0000 Subject: [PATCH 3/6] Convert the protocol to use JSON-RPC Signed-off-by: Stephen Curran --- features/0804-didcomm-rpc/README.md | 454 ++++++++++++++-------------- 1 file changed, 231 insertions(+), 223 deletions(-) diff --git a/features/0804-didcomm-rpc/README.md b/features/0804-didcomm-rpc/README.md index 295596ff4..2b8ba7280 100644 --- a/features/0804-didcomm-rpc/README.md +++ b/features/0804-didcomm-rpc/README.md @@ -10,60 +10,81 @@ ## Summary -The DIDComm RPC (DRPC) protocol allows a remote request-response interaction, a -Remote Procedure Call (RPC), to be carried out through a -DIDComm channel. The requesting Aries agent sends a DIDComm message to request the remote -service be invoked, and gets back the response in another DIDComm message. The -protocol enables any request to be conveyed, and the subsequent response to be -returned, with flexibility in the formats (JSON, Base64 encoded) sent and -received. Out of scope of this protocol is how the requesting agent -discovers the services available from the responding agent, and how the two -agents know about the semantics of the requests and responses. By using DIDComm -between the requesting and responding agents, the security and privacy benefits -of DIDComm are accomplished, and the generic payloads of the messages allows for -flexibility in how and where the protocol can be used. +The DIDComm Remote Procedure Call (DRPC) protocol enables a [JSON-RPC]-based +request-response interaction to be carried out across a DIDComm channel. The +protocol is designed to enable custom interactions between connected agents, and +to allow for the rapid prototyping of experimental DIDComm protocols. An agent +sends a DIDComm message to request a remote service be invoked by another agent, +and gets back a response in subsequent DIDComm message. The protocol enables any +request to be conveyed that the other agent understands. Out of scope of this +protocol is how the requesting agent discovers the services available from the +responding agent, and how the two agents know the semantics of the [JSON-RPC] +requests and responses. By using DIDComm between the requesting and responding +agents, the security and privacy benefits of DIDComm are accomplished, and the +generic parameters of the messages allow for flexibility in how and where the +protocol can be used. + +[JSON-RPC]: https://www.jsonrpc.org/specification ## Motivation -There are several use cases that are driving the need for this protocol: +There are several use cases that are driving the initial need for this protocol. ### App Attestation -- A mobile wallet needs to get an [app attestation] verifiable credential from - the wallet publisher. To do that, the wallet and publisher need to exchange - information specific to to the attestation process with the Google and Apple - stores. The sequence is as follows: - - The wallet decides (for some reason) it needs an App Attestation credential from its publisher. - - If not already available, a DIDComm connection between the wallet and the attestation service is created. - - The wallet uses the RPC protocol to request a nonce from the service to be used in the attestation. The service responds with the nonce. - - The wallet uses a new instance of the RPC protocol to request the attestation be performed. The service responds with the status of the attestation process. - - The service completes the business process by initiating an Issue Credential process to issue an attestation verifiable credential. - -The wallet and service are using instances of three protocols (two RPC and one -Issue Credential) to carry out a full business process. Each must have knowledge -of the full business process--there is nothing inherent in the RPC protocol -about this process, or how it is being used. The RPC protocol is included to -provide a generic request-response mechanism that alleviates the need for building -many special purpose protocols. +A mobile wallet needs to get an [app attestation] verifiable credential from +the wallet publisher. To do that, the wallet and publisher need to exchange +information specific to to the attestation process with the Google and Apple +stores. The sequence is as follows: + +- The wallet decides (for some reason) it needs an App Attestation credential + from its publisher. +- If not already available, a DIDComm connection between the wallet and the + attestation service is created. +- The wallet uses the RPC protocol to request a nonce from the service to be + used in the attestation. The service responds with the nonce. +- The wallet uses a new instance of the RPC protocol to request the attestation + be performed. The service responds with the status of the attestation process. +- The service completes the business process by initiating an Issue Credential + process to issue an attestation verifiable credential. + +The wallet and service are using instances of three protocols (two DRPC and one +Issue Credential) to carry out a full business process. Each participant must +have knowledge of the full business process--there is nothing inherent in the +DRPC protocol about this process, or how it is being used. The DRPC protocol is +included to provide a generic request-response mechanism that alleviates the +need for formalizing special purpose protocols. + +> App attestation is a likely candidate for a having its own DIDComm protocol. +> This use of DRPC is ideal for developing and experimenting with the necessary +> agent interactions before deciding on if a use-specific protocol is needed and +> its semantics. [app attestation]: https://developer.apple.com/documentation/devicecheck ### Video Verification Service -A second example is using the RPC protocol is to implement a video verification -service that is performed prior to issuing a credential to a wallet. In this -example, the wallet communicates over DIDComm to a Credential Issuer agent that -(during verification) is a proxy to an HTTP-based video verification service. -Rather than establishing a separate, direct channel between the wallet and the -verification service, the DIDComm channel with the Issuer service is used, and -during video verification, the Issuer agent passes data between the wallet -collecting the video data and the verification service directing the process and -receiving/reviewing the data. The wallet implements the requests needed to carry -out the steps of the verification, sending to the Issuer agent the necessary -requests. The Issuer conveys the requests to the verification service and the -responses back to the mobile wallet. At the end of the process, the Issuer can -see the result of the process, and decides on next steps between it and the -mobile wallet. +A second example is using the DRPC protocol is to implement a custom video +verification service that is used by a specific mobile wallet implementation and +a proprietary backend service prior to issuing a credential to the wallet. Since +the interactions are to a proprietary service, so an open specification does not +make sense, but the use of DIDComm is valuable. In this example, the wallet +communicates over DIDComm to a Credential Issuer agent that (during +verification) proxies the requests/responses to a backend ("behind the +firewall") service. The wallet is implemented to use DRPC protocol instances to +initiate the verification and receive the actions needed to carry out the steps +of the verification (take picture, take video, instruct movements, etc.), +sending to the Issuer agent the necessary data. The Issuer conveys the +requests to the verification service and the responses back to the mobile +wallet. At the end of the process, the Issuer can see the result of the process, +and decide on the next actions between it and the mobile wallet, such as issuing a +credential. + +Again, after using the DRPC protocol for developing and experimenting with the +implementation, the creators of the protocol can decide to formalize their own +custom, end-to-end protocol, or continue to use the DRPC protocol instances. +Important is that they can begin without doing any custom Aries frameworks or +plugins. ## Tutorial @@ -79,99 +100,122 @@ This is the DRPC protocol. It is uniquely identified by the URI: [DID communication]: /concepts/0005-didcomm/README.md -This protocol consists of a message type to carry an arbitrary request to a -responding agent, and a second message that carries the result of processing the -request back to the sender of the first message. The interpretation of the -request, how to carry out the request, the content of the response, and the -interpretation of the response, are all up to the business logic (controllers) -of the participating agents. There is no discovery of remote services offered by -agents--it is assumed that the two participants are aware of the RPC -capabilities of one another through some other means. For example, from the [App -Attestation use case](#app-attestation), functionality to carry out the app -attestation process, and the service to use is built into the mobile wallet. +The protocol consists of a DIDComm `request` message carrying an arbitrary +[JSON-RPC] request to a responding agent, and a second message that carries the +result of processing the request back to the client of the first message. The +interpretation of the request, how to carry out the request, the content of the +response, and the interpretation of the response, are all up to the business +logic (controllers) of the participating agents. There is no discovery of remote +services offered by agents--it is assumed that the two participants are aware of +the DRPC capabilities of one another through some other means. For example, from +the [App Attestation use case](#app-attestation), functionality to carry out the +app attestation process, and the service to use it is built into the mobile wallet. + +Those unfamiliar with [JSON-RPC], the `` is that it is a very simple +request response protocol using JSON where the only data shared is: + +- a `method` that defines what needs to be done, +- some `params` in JSON that are up to the requester/server to agree on, and +- an `id` to connect the response to the request. + +An example of a simple [JSON-RPC] request/response pair from the specification is: + +``` +--> {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1} +<-- {"jsonrpc": "2.0", "result": 19, "id": 1} +``` + +As will be seen in the DRPC messages below, the protocol uses the [JSON-RPC] +format, leaving off the `id` in favor of the DIDComm `id` / `thid` model. + +[JSON-RPC] follows a very similar pattern to DIDComm. As a result, in this +protocol we do not need to add any special handling around the `params` such as +Base64 encoding, signing, headers and so on, as the parties interacting with the +protocol by definition must have a shared understanding of the content of the +`params` and can define any special handling needed amongst themselves. It is expected (although not required) that an Aries Framework receiving a DRPC message will simply pass to its associated "business logic" (controller) the -request from the sender, and waiting on the controller to provide the response -content to send back to the original sender. Apart from the messaging processing +request from the client, and wait on the controller to provide the response +content to be sent back to the original client. Apart from the messaging processing applied to all inbound and outbound messages, the Aries Framework will not perform any of the actual processing of the request. ### Roles -There are two roles in the protocol `sender` and `responder`: +There are two roles, adopted from the [JSON-RPC] specification, in the protocol +`client` and `server`: -- The `sender` initiates the protocol, sending a request to the `responder`. -- The `responder` carries out the request however they see fit. The `responder` +- The `client` initiates the protocol, sending a request to the `server`. +- The `server` carries out the request however they see fit. The `server` may process the request themselves, or might invoke another service to process - the request. The `responder` might be unable or unwilling to carry out the + the request. The `server` might be unable or unwilling to carry out the request. -- The `responder` returns the response from the request in a message to the `sender`. +- The `server` returns the response from the request in a message to the `client`. ### States -#### Sender +#### Client States -The `sender` agent goes through the following states: +The `client` agent goes through the following states: - request-sent -- abandoned - completed -The state transition table for the `sender` is: +The state transition table for the `client` is: -| State / Events | Send Request | Receive Response | Receive Ack | Receive Problem Report | -| -------------- | ---------------------------------- | ------------------------------ | ------------------------------ | ------------------------------- | -| *Start* | Transition to
**request-sent** | | | | -| request-sent | | Transition to
**complete** | Transition to
**complete** | Transition to
**abandoned** | -| completed | | | | | -| abandoned | | | | | +| State / Events | Send Request | Receive Response | +| -------------- | ---------------------------------- | ------------------------------ | +| *Start* | Transition to
**request-sent** | | +| request-sent | | Transition to
**complete** | +| completed | | | -#### Responder +#### Server States -The `responder` agent goes through the following states: +The `server` agent goes through the following states: - request-received -- abandoned - completed -The state transition table for the `responder` is: +The state transition table for the `server` is: -| State / Events | Receive Request | Send Response | Send Ack | Send Problem Report | -| ---------------- | -------------------------------------- | ------------------------------ | ------------------------------ | ------------------------------- | -| *Start* | Transition to
**request-received** | | | | -| request-received | | Transition to
**complete** | Transition to
**complete** | Transition to
**abandoned** | -| completed | | | | | -| abandoned | | | | | +| State / Events | Receive Request | Send Response | +| ---------------- | -------------------------------------- | ------------------------------ | +| *Start* | Transition to
**request-received** | | +| request-received | | Transition to
**complete** | +| completed | | | ### Messages -The following are the messages in the DRPC protocol, including the adopted messages. +The following are the messages in the DRPC protocol. The `response` message +handles all possible responses, so the `ack` ([RFC 0015 ACKs]) and +`problem-report` ([RFC 0035 Report Problem]) messages are **NOT** adopted by +this protocol. -#### Request Message +[RFC 0015 ACKs]: /features/0015-acks/README.md) +[RFC 0035 Report Problem]: /features/0035-report-problem/README.md -The `request` message is sent by the `sender` to initiate the protocol. The -message contains the information necessary for the `responder` to process the -request, prepare the response, and send the response message back. It is assumed -the `sender` knows what types of requests the `responder` is prepared to receive -and process. How the `sender` and `responder` coordinate that understanding is -out of scope of this protocol. +#### Request Message -The `request` message items have been chosen to make putting an HTTP request -into the `request` message easy (borrowing from [RFC 0335 HTTP Over -DIDComm]), but an HTTP request is not required. As long as `request_type` -identifies the request being made, and the `responder` understands it, the -message can be processed. +The `request` message is sent by the `client` to initiate the protocol. The +message contains the [JSON-RPC] information necessary for the `server` to +process the request, prepare the response, and send the response message back to +the `client`. It is assumed the `client` knows what types of requests the +`server` is prepared to receive and process. If the `server` does not know how +to process the error, [JSON-RPC] has a standard response, outlined in the +[response message](#response-message) section below. How the `client` and +`server` coordinate that understanding is out of scope of this protocol. -[RFC 0335 HTTP Over DIDComm]: /features/0335-http-over-didcomm/README.md +The `request` message uses the same JSON items as [JSON-RPC], skipping the +`id` in favor of the existing DIDComm `@id` and thread handling. ```jsonc { "@type": "https://didcomm.org/drpc/1.0/request", "@id": "2a0ec6db-471d-42ed-84ee-f9544db9da4b", - "request": "", - "headers": [{"name": "Content-Type", "value": "application/json"}], - "body.base64": "" + "jsonrpc" : "2.0", + "method": "string", + "params": "" } ``` @@ -179,49 +223,42 @@ The items in the message are as follows: - `@type` -- required, must be as above - `@id` -- required, must be as defined in [RFC 0005 DIDComm] -- `request_type` -- **required**, an identifier indicating the type of the request. The value could be a URI, such as an HTTP URL, that the `sender` would like `responder` to resolve, or the value could be just a string understood by the `responder`. -- `headers` -- optional, a JSON array typically used for conveying HTTP headers to be used in the processing of an HTTP URL `request_type`. As with all parts of this protocol, the meaning is up to the participants of an instance of the protocol. - - Each element of the array is an object with two elements: `{"name": "", "value": ""}`. - - When a `body` is included, a **required** element in the array is `"name": "Content-Type"` with the `"value"` being the `body`'s [MIME Type] (also know as the media type). -- `body.base64` -- optional, the [Base64 encoded] body of the request. - - When Base64 decoded, the result must be in the format defined by the `Content-Type` value in the `headers` array. - -[MIME Type]: https://developer.mozilla.org/en-US/docs/Glossary/MIME_type -[Data URL]: https://en.wikipedia.org/wiki/Data_URI_scheme -[Base64 encoded]: https://en.wikipedia.org/wiki/Base64 - -The `responder` processing an HTTP request may want to scan and account for the -HTTP headers defined by the `sender` For example, the `responder` might detect -and respect the timeout parameter provided in a keep-alive header if the request -header is a keep-alive connection. +- `jsonrpc` -- **required**, a string specifying the version of the [JSON-RPC] protocol. Currently "2.0", but may change over time. +- `method` -- **required**, A string containing the name of the method to be invoked. + - Method names that begin with the word rpc followed by a period character (U+002E or ASCII 46) are reserved for rpc-internal methods and extensions and **MUST NOT** be used for anything else. +- `params` -- optional, a JSON structured value that holds the parameter values to be used during the invocation of the method. + +Since the [JSON-RPC] `id` is automatically included in the DIDComm `request` +message via the DIDComm `@id`, the [JSON-RPC] request of the form `Notification` +is not supported. + +Batch submission of [JSON-RPC] requests is *NOT* supported. #### Response Message -A `response` message is usually sent by the `responder` to following the +A `response` message is sent by the `server` to following the processing of the request to convey the output of the processing to the -`sender`. It is assumed the `sender` understands what the contents of the -`response` message means in the context of the protocol instance. How the -`sender` and `responder` coordinate that understanding is out of scope of this -protocol. In some cases the `responder` may choose to send an [Adopted -ACK](#adopted-ack) or an [Adopted Problem Report](#adopted-problem-report) -instead of the `response` message, as described below. +`client`. As with the `request` the format mostly matches that of a +[JSON-RPC] response, with the exception of the `id`, which is handled +via the `DIDComm` `~thread.thid`. -The message items have been chosen to make putting the response of an HTTP -request into the `response` message easy (borrowing directly from [RFC 0335 HTTP -Over DIDComm]), but an HTTP response is not required. As long as the `sender` -understands the contents of the items, the message can be processed. +It is assumed the `client` understands what the contents of the +`response` message means in the context of the protocol instance. How the +`client` and `server` coordinate that understanding is out of scope of this +protocol. ```jsonc { "@type": "https://didcomm.org/drpc/1.0/response", "@id": "63d6f6cf-b723-4eaf-874b-ae13f3e3e5c5", - "status": { - "code":"", - "string":"" - }, - "headers": [{"name": "Content-Type", "value": "application/json"}], - "body.base64": "" + "jsonrpc": "2.0", + "result": "", + "error": { + "code": 1, + "message": "string", + "data": "" + } } ``` @@ -230,81 +267,53 @@ The items in the message are as follows: - `@type` -- required, must be as above - `@id` -- required, must be as defined in [RFC 0005 DIDComm] - `status` -- optional, can be used to indicate the status of an HTTP request. -- `headers` -- optional, a JSON array typically used for conveying HTTP headers to be used in the processing of an HTTP URL `request_type`. As with all parts of this protocol, the meaning is up to the participants of an instance of the protocol. -- `headers` -- optional, a JSON array typically used for conveying HTTP headers resulting from the processing of an HTTP URL `request`. As with all parts of this protocol, the meaning is up to the participants of an instance of the protocol. - - Each element of the array is an object with two elements: `{"name": "", "value": ""}`. - - When a `body` is included, a **required** element in the array is `"name": "Content-Type"` with the `"value"` being the `body`'s [MIME Type] (also know as the media type). -- `body.base64` -- optional, the [Base64 encoded] body of the request. - - When Base64 decoded, the result must be in the format defined by the `Content-Type` value in the `headers` array. - +- `result` -- optional, a JSON item whose value is determined by the method invoked by the `server`. + - **REQUIRED** on success. + - **MUST NOT** exist if there was an error invoking the method. +- `error` -- optional, **REQUIRED** if there was an error invoking the methof, and **MUST NOT** exist if there was not an error triggered during invocation. + - If included, the following are the fields in the `error` item: + - `code` -- **requred**, an integer that indicates the error type that occurred. + - `message` -- **required**, a string providing a short description of the error, that **SHOULD** be limited to a concise single sentence. + - `data` -- optional, a JSON item (primitive or structured) that contains additional information about the error. + - The value of this item is defined by the `server` (e.g., detailed error information, nested errors etc.). As with all DIDComm messages that are not the first in a protocol instance, a `~thread` decorator **MUST** be included in the `response` message. -#### Adopted ACK - -Since all of the items in the [Response Message](#response-message) are -optional, in some cases it might be easier for a `responder` to simply respond -to a `request` with an adopted [RFC 0015 ACKs] message, indicating without -further detail that the `request` was processed successfully. - -[RFC 0015 ACKs]: /features/0015-acks/README.md) - -```jsonc - - { - "@type": "https://didcomm.org/notification/1.0/ack", - "@id": "06d474e0-20d3-4cbf-bea6-6ba7e1891240", - "status": "OK" - } - -``` - -#### Adopted Problem Report - -In some cases, a `responder` may be unwilling or unable to complete the -`request` from the `sender`. For example, if the `responder` does not understand -the `request_type`, they obviously cannot process the request. In such cases, -the `responder` **SHOULD** send a [RFC 0035 Report Problem] problem report, with -as much detail as needed. - -In other cases, the `responder` may try to process the `request` and get an -error in the processing. The `responder` has the option of sending a `response` -message with the available details of the processing error or sending a [RFC -0035 Report Problem]. For example, if the `request` was to resolve an HTTP URL, -and the HTTP `request` failed, the best response might be to send the HTTP -response that was received in a DRPC `response` messages. In other cases where -the `responder` itself processed the `request`, a problem report might be a more -useful to the `sender`. - -[RFC 0035 Report Problem]: /features/0035-report-problem/README.md +If the `server` does not understand how to process the request, a `response` +error should be returned with the `error.code` value `-32601`, `error.message` +set to `Method not found`, and no `error.data` item, as per the [JSON-RPC] +specification. ### Constraints The primary constraint with this protocol is that the two parties using the -protocol must understand one another--what `request_type` to use, what to -provide in the `headers` and `body`, how to process the `request`, what the -`response` means, and so on. It is not a protocol to be used between arbitrary -parties, but rather one where the parties have knowledge outside of DIDComm of -one another and their mutual capabilities. - -On the other hand, that constrain enables great flexibility, allowing -collaborating agents to accomplish almost any request-response transaction over -DIDComm without needing to define additional DIDComm protocols. More complex -interactions can be accomplished by carrying out a sequence of DRPC protocol -instances between agents. - -The flexibility DRPC protocol allows for experimenting with interactions between -agents that could later evolve into formal DIDComm protocols designed for a -specific purpose. +protocol must understand one another--what `method` to use, what to provide in +the `params`, how to process the `request`, what the `response` means, and so +on. It is not a protocol to be used between arbitrary parties, but rather one +where the parties have knowledge outside of DIDComm of one another and their +mutual capabilities. + +On the other hand, that constraint enables great flexibility for explicitly +collaborating agents (such as a mobile wallet and the agent of its manufacturer) +to accomplish request-response transactions over DIDComm without +needing to define additional DIDComm protocols. More complex interactions can be +accomplished by carrying out a sequence of DRPC protocol instances between +agents. + +The flexibility the DRPC protocol allows for experimenting with specific +interactions between agents that could later evolve into formal DIDComm "fit for +purpose" protocols. ## Reference ### Codes Catalog -A `request_type` codes catalog *could* be developed over time and included -in this part of the RFC. This might the first step in transitioning a given -interaction implemented using DRPC into formally specified interaction. +A `method` codes catalog *could* be developed over time and be included in this +part of the RFC. This might an additional step in transitioning a given +interaction implemented using DRPC into formally specified interaction. On the +other hand, simply defining a full DIDComm protocol will often be a far better +approach. At this time, there are no codes to be cataloged. @@ -312,9 +321,9 @@ At this time, there are no codes to be cataloged. Anything that can be done by using the DRPC protocol can be accomplished by a formally defined protocol specific to the task to be accomplished. The advantage -of the DRPC protocol is that pairs of agent instances that are collaborating can -use the protocol to collaborate without having to first define a task-specific -protocol. +of the DRPC protocol is that pairs of agent instances that are explicitly +collaborating can use this protocol without having to first define a +task-specific protocol. ## Rationale and alternatives @@ -322,54 +331,53 @@ This design builds on the experience of implementations of this kind of feature using [RFC 0095 Basic Message] and [RFC 0335 HTTP Over DIDComm]. This design tries to build off the learnings gained from both of those implementations. -## Prior art +Based on feedback to an original version of the RFC, we looked as well at +using [gRPC] as the core of this protocol, versus [JSON-RPC]. Our assessment +was that [gRPC] was a much heavier weight mechanism that required more effort +between parties to define and implement what will often be a very simple +request-response transaction -- at the level of defining a DIDComm protocol. + +[gRPC]: https://grpc.io/ + +The use of `params` and leaving the content and semantics of the params up to +the `client` and `server` means that they can define the appropriate handling of +the parameters. This eliminates the need for the protocol to define, for +example, that the data needs to be Base64 encoding for transmission, or if some +values need to be cryptographically signed. Such details are left to the +participants and how they are using the protocol. -This protocol is very similar to the [RFC 0335 HTTP Over DIDComm] protocol, -borrowing heavily from its design and concepts. The motivations for adding this protocol versus -simply using that existing protocol are as follows. +## Prior art -- To enable other types of requests, beyond HTTP, to be handled using the protocol. -- To relieve the Aries Framework from any role in the execution of the protocol. - With [RFC 0335 HTTP Over DIDComm], it is possible that the Aries Framework - could handle the HTTP request/response, without engaging the business logic - (controller) of the agent. This protocol strongly recommends that the - controller handle the processing. -- Enables, when processing requests to resolve HTTP URLs, the controller to - handle any necessary authorizations with the HTTP-based service being called. -- It is not clear what role the `~purpose` item (based on [RFC 0351 Purpose - Decorator]) plays and how it should be used in the relatively simple use cases - envisioned being implemented using this protocol. +This protocol has similar goals to the [RFC 0335 HTTP Over DIDComm] protocol, +but takes a lighter weight, more flexible approach. We expect that implementing +HTTP over DIDComm using this protocol will be as easy as using [RFC 0335 HTTP +Over DIDComm], where the `params` data structure holds the `headers` and `body` +elements for the HTTP request. On the other hand, using the explicit [RFC 0335 +HTTP Over DIDComm] is likely a better choice if it is available and needed. -[RFC 0351 Purpose Decorator]: /concepts/0351-purpose-decorator/README.md +[RFC 0335 HTTP Over DIDComm]: /features/0335-http-over-didcomm/README.md One of the example use cases for this protocol has been implemented by "hijacking" the [RFC 0095 Basic Message] protocol to carry out the needed request/response actions. This approach is less than ideal in that: - That is not the intended use of [RFC 0095 Basic Message], which is to send a - basic, human consumable, message to the other agent. -- The `request_type` and all of the parameters for the request have to be encoded into the basic message. + basic, human consumable message to the other agent. +- The request method and parameters have to be encoded into the basic message. - The [RFC 0095 Basic Message] protocol is a single message protocols, so each - request-response interaction requires tow instances of the protocol, and for + request-response interaction requires two instances of the protocol, and for the controllers to manage connecting the interactions together. [RFC 0095 Basic Message]: /features/0095-basic-message/README.md -Since this protocol can be used in place of [RFC 0335 HTTP Over DIDComm], its -prior art comments likewise apply to the DRPC protocol: - -- VPNs and onion routing (like Tor) provide solutions for similar use cases, but none so far use DIDs, which enable more complex use cases with privacy preservation. - - TLS/HTTPS, being HTTP over TLS, provides a similar transport-layer secure channel to HTTP over DIDComm. Note, this is why this RFC doesn't specify a means to perform HTTPS over DIDComm - DIDComm serves the same role as TLS does in HTTPS, but offers additional benefits: - - Verifiable yet anonymous authentication of the client, for example, using delegated credentials. - - Access to DIDComm mechanisms, such as using the introduce protocol to connect the client and server. - ## Unresolved questions +- [JSON-RPC] includes the concept of batch requests, where a set of [JSON-RPC] objects are included in a single request. Should we add support for batch requests to this DRPC protocol? +- [JSON-RPC] includes the concept of a "notification" request, where a response to the request is not needed. Should we add support for notification requests to this DRPC protocol? - Should we include the idea of a `request` having a goal code ([RFC 0519 Goal Codes])? -- Should we simply use [RFC 0335 HTTP Over DIDComm]? [RFC 0519 Goal Codes]: /concepts/0519-goal-codes/README.md - + ## Implementations The following lists the implementations (if any) of this RFC. Please do a pull request to add your implementation. If the implementation is open source, include a link to the repo or to the implementation within the repo. Please be consistent in the "Name" field so that a mechanical processing of the RFCs can generate a list of all RFCs supported by an Aries implementation. From a92239ac05b54822dee030db2624c591ee0a44e1 Mon Sep 17 00:00:00 2001 From: Stephen Curran Date: Mon, 11 Dec 2023 23:44:00 +0000 Subject: [PATCH 4/6] Update to make the request and response fields full JSON-RPC requests/responses Signed-off-by: Stephen Curran --- features/0804-didcomm-rpc/README.md | 158 +++++++++++++++------------- 1 file changed, 83 insertions(+), 75 deletions(-) diff --git a/features/0804-didcomm-rpc/README.md b/features/0804-didcomm-rpc/README.md index 2b8ba7280..7fd4224d0 100644 --- a/features/0804-didcomm-rpc/README.md +++ b/features/0804-didcomm-rpc/README.md @@ -14,15 +14,15 @@ The DIDComm Remote Procedure Call (DRPC) protocol enables a [JSON-RPC]-based request-response interaction to be carried out across a DIDComm channel. The protocol is designed to enable custom interactions between connected agents, and to allow for the rapid prototyping of experimental DIDComm protocols. An agent -sends a DIDComm message to request a remote service be invoked by another agent, -and gets back a response in subsequent DIDComm message. The protocol enables any -request to be conveyed that the other agent understands. Out of scope of this -protocol is how the requesting agent discovers the services available from the -responding agent, and how the two agents know the semantics of the [JSON-RPC] -requests and responses. By using DIDComm between the requesting and responding -agents, the security and privacy benefits of DIDComm are accomplished, and the -generic parameters of the messages allow for flexibility in how and where the -protocol can be used. +sends a DIDComm message to request a [JSON-RPC] service be invoked by another +agent, and gets back the [JSON-RPC]-format response in subsequent DIDComm +message. The protocol enables any request to be conveyed that the other agent +understands. Out of scope of this protocol is how the requesting agent discovers +the services available from the responding agent, and how the two agents know +the semantics of the specified [JSON-RPC] requests and responses. By using +DIDComm between the requesting and responding agents, the security and privacy +benefits of DIDComm are accomplished, and the generic parameters of the requests +allow for flexibility in how and where the protocol can be used. [JSON-RPC]: https://www.jsonrpc.org/specification @@ -41,9 +41,9 @@ stores. The sequence is as follows: from its publisher. - If not already available, a DIDComm connection between the wallet and the attestation service is created. -- The wallet uses the RPC protocol to request a nonce from the service to be +- The wallet uses the DRPC protocol to request a nonce from the service to be used in the attestation. The service responds with the nonce. -- The wallet uses a new instance of the RPC protocol to request the attestation +- The wallet uses a new instance of the DRPC protocol to request the attestation be performed. The service responds with the status of the attestation process. - The service completes the business process by initiating an Issue Credential process to issue an attestation verifiable credential. @@ -74,17 +74,16 @@ verification) proxies the requests/responses to a backend ("behind the firewall") service. The wallet is implemented to use DRPC protocol instances to initiate the verification and receive the actions needed to carry out the steps of the verification (take picture, take video, instruct movements, etc.), -sending to the Issuer agent the necessary data. The Issuer conveys the -requests to the verification service and the responses back to the mobile -wallet. At the end of the process, the Issuer can see the result of the process, -and decide on the next actions between it and the mobile wallet, such as issuing a -credential. +sending to the Issuer agent the necessary data. The Issuer conveys the requests +to the verification service and the responses back to the mobile wallet. At the +end of the process, the Issuer can see the result of the process, and decide on +the next actions between it and the mobile wallet, such as issuing a credential. Again, after using the DRPC protocol for developing and experimenting with the implementation, the creators of the protocol can decide to formalize their own custom, end-to-end protocol, or continue to use the DRPC protocol instances. -Important is that they can begin without doing any custom Aries frameworks or -plugins. +Important is that they can begin development without doing any Aries frameworks +customizations or plugins by using DRPC. ## Tutorial @@ -116,7 +115,13 @@ request response protocol using JSON where the only data shared is: - a `method` that defines what needs to be done, - some `params` in JSON that are up to the requester/server to agree on, and -- an `id` to connect the response to the request. +- an (optional) `id` to connect the response to the request. + +The response is likewise simple: + +- a `result` item if the invocation completed successful containing the return results, +- an `error` item if the invocation failed, containing details about the failure, and +- the `id` from the request. An example of a simple [JSON-RPC] request/response pair from the specification is: @@ -125,14 +130,15 @@ An example of a simple [JSON-RPC] request/response pair from the specification i <-- {"jsonrpc": "2.0", "result": 19, "id": 1} ``` -As will be seen in the DRPC messages below, the protocol uses the [JSON-RPC] -format, leaving off the `id` in favor of the DIDComm `id` / `thid` model. +A [JSON-RPC] request may be a batch of requests, each with a different `id` value, +and the response a similar array, with an entry for each of the requests. -[JSON-RPC] follows a very similar pattern to DIDComm. As a result, in this -protocol we do not need to add any special handling around the `params` such as -Base64 encoding, signing, headers and so on, as the parties interacting with the -protocol by definition must have a shared understanding of the content of the -`params` and can define any special handling needed amongst themselves. +[JSON-RPC] follows a similar "parameters defined by the message type" pattern as +DIDComm. As a result, in this protocol we do not need to add any special +handling around the `params` such as Base64 encoding, signing, headers and so +on, as the parties interacting with the protocol by definition must have a +shared understanding of the content of the `params` and can define any special +handling needed amongst themselves. It is expected (although not required) that an Aries Framework receiving a DRPC message will simply pass to its associated "business logic" (controller) the @@ -213,9 +219,7 @@ The `request` message uses the same JSON items as [JSON-RPC], skipping the { "@type": "https://didcomm.org/drpc/1.0/request", "@id": "2a0ec6db-471d-42ed-84ee-f9544db9da4b", - "jsonrpc" : "2.0", - "method": "string", - "params": "" + "request" : " request" } ``` @@ -223,24 +227,23 @@ The items in the message are as follows: - `@type` -- required, must be as above - `@id` -- required, must be as defined in [RFC 0005 DIDComm] -- `jsonrpc` -- **required**, a string specifying the version of the [JSON-RPC] protocol. Currently "2.0", but may change over time. -- `method` -- **required**, A string containing the name of the method to be invoked. - - Method names that begin with the word rpc followed by a period character (U+002E or ASCII 46) are reserved for rpc-internal methods and extensions and **MUST NOT** be used for anything else. -- `params` -- optional, a JSON structured value that holds the parameter values to be used during the invocation of the method. - -Since the [JSON-RPC] `id` is automatically included in the DIDComm `request` -message via the DIDComm `@id`, the [JSON-RPC] request of the form `Notification` -is not supported. +- `request` -- **required**, an item containing a [JSON-RPC] request JSON structure. + - `request` **MUST** be either a single [JSON-RPC] request, or an array of [JSON-RPC] requests. + - Each [JSON-RPC] request **MUST** have the `jsonrpc` and `method` items. + - Each [JSON-RPC] request **MAY** have the `params` and `id` items. + - See the details below about the handling of `notification` [JSON-RPC] requests, requests where the `id` field is omitted. + - See the [JSON-RPC] specification for details about the `jsonrpc`, `method`, `params` and `id` JSON items. -Batch submission of [JSON-RPC] requests is *NOT* supported. +Per the [JSON-RPC] specification, if the `id` field of a [JSON-RPC] request is omitted, the `server` should not respond. In this DRPC DIDComm protocol, the `server` is always expected to send a `response`, but **MUST NOT** include +a [JSON-RPC] response for any [JSON-RPC] request for which the `id` is omitted. This is covered further +in the [response message](#response-message) section (below). #### Response Message A `response` message is sent by the `server` to following the processing of the request to convey the output of the processing to the -`client`. As with the `request` the format mostly matches that of a -[JSON-RPC] response, with the exception of the `id`, which is handled -via the `DIDComm` `~thread.thid`. +`client`. As with the `request` the format mostly exactly that of a +[JSON-RPC] response. It is assumed the `client` understands what the contents of the `response` message means in the context of the protocol instance. How the @@ -252,13 +255,7 @@ protocol. { "@type": "https://didcomm.org/drpc/1.0/response", "@id": "63d6f6cf-b723-4eaf-874b-ae13f3e3e5c5", - "jsonrpc": "2.0", - "result": "", - "error": { - "code": 1, - "message": "string", - "data": "" - } + "response": " response" } ``` @@ -266,21 +263,24 @@ The items in the message are as follows: - `@type` -- required, must be as above - `@id` -- required, must be as defined in [RFC 0005 DIDComm] -- `status` -- optional, can be used to indicate the status of an HTTP request. -- `result` -- optional, a JSON item whose value is determined by the method invoked by the `server`. - - **REQUIRED** on success. - - **MUST NOT** exist if there was an error invoking the method. -- `error` -- optional, **REQUIRED** if there was an error invoking the methof, and **MUST NOT** exist if there was not an error triggered during invocation. - - If included, the following are the fields in the `error` item: - - `code` -- **requred**, an integer that indicates the error type that occurred. - - `message` -- **required**, a string providing a short description of the error, that **SHOULD** be limited to a concise single sentence. - - `data` -- optional, a JSON item (primitive or structured) that contains additional information about the error. - - The value of this item is defined by the `server` (e.g., detailed error information, nested errors etc.). +- `response` -- **required**, an item containing a [JSON-RPC] response JSON structure. + - `response` **MUST** be either single (possibly empty) [JSON-RPC] response, or an array of [JSON-RPC] requests. + - If all of the [JSON-RPC] requests in the `request` message are + *notifications* (e.g., the `id` item is omitted), the DIDComm `response` + message **MUST** be sent back with a value: `"response" : {}`. + - Each [JSON-RPC] response **MUST** have the `jsonrpc` and `id` items, and either a `result` or `error` item. + - See the [JSON-RPC] specification for details about the `jsonrpc`, `id`, `result` and `error` JSON items. As with all DIDComm messages that are not the first in a protocol instance, a `~thread` decorator **MUST** be included in the `response` message. -If the `server` does not understand how to process the request, a `response` +The special handling of the "all [JSON-RPC] requests are notifications" is to +simplify the DRPC handling to know when a DRPC protocol instance is complete. If +a `response` message is not always required, the DRPC handler would have to +inspect the `request` message to look for `id`s to determine when the protocol +completes. + +If the `server` does not understand how to process a [JSON-RPC] request, a `response` error should be returned with the `error.code` value `-32601`, `error.message` set to `Method not found`, and no `error.data` item, as per the [JSON-RPC] specification. @@ -288,11 +288,11 @@ specification. ### Constraints The primary constraint with this protocol is that the two parties using the -protocol must understand one another--what `method` to use, what to provide in -the `params`, how to process the `request`, what the `response` means, and so -on. It is not a protocol to be used between arbitrary parties, but rather one -where the parties have knowledge outside of DIDComm of one another and their -mutual capabilities. +protocol must understand one another--what [JSON-RPC] request(s) to use, what +parameters to provide, how to process the those requests, what the `response` +means, and so on. It is not a protocol to be used between arbitrary parties, but +rather one where the parties have knowledge outside of DIDComm of one another +and their mutual capabilities. On the other hand, that constraint enables great flexibility for explicitly collaborating agents (such as a mobile wallet and the agent of its manufacturer) @@ -309,11 +309,11 @@ purpose" protocols. ### Codes Catalog -A `method` codes catalog *could* be developed over time and be included in this -part of the RFC. This might an additional step in transitioning a given -interaction implemented using DRPC into formally specified interaction. On the -other hand, simply defining a full DIDComm protocol will often be a far better -approach. +A [JSON-RPC] request codes catalog *could* be developed over time and be +included in this part of the RFC. This might an intermediate step in transitioning +a given interaction implemented using DRPC into formally specified interaction. +On the other hand, simply defining a full DIDComm protocol will often be a far +better approach. At this time, there are no codes to be cataloged. @@ -327,6 +327,15 @@ task-specific protocol. ## Rationale and alternatives +We considered not supporting the *notification* and *batch* forms of the +[JSON-RPC] specification, and decided it made sense to allow for the full +support of the [JSON-RPC] specification, including requests of those forms. That +said, we also found that the concept of **not** having a DRPC `response` message +in some (likely, rare) cases based on the contents of the `request` JSON item +(e.g., when all of the `id`s are omitted from the [JSON-RPC] requests) would +unnecessarily complicate the DIDComm protocol instance handling about when it is +complete. As a result, a DRPC `response` message is always required. + This design builds on the experience of implementations of this kind of feature using [RFC 0095 Basic Message] and [RFC 0335 HTTP Over DIDComm]. This design tries to build off the learnings gained from both of those implementations. @@ -342,7 +351,7 @@ request-response transaction -- at the level of defining a DIDComm protocol. The use of `params` and leaving the content and semantics of the params up to the `client` and `server` means that they can define the appropriate handling of the parameters. This eliminates the need for the protocol to define, for -example, that the data needs to be Base64 encoding for transmission, or if some +example, that some data needs to be Base64 encoding for transmission, or if some values need to be cryptographically signed. Such details are left to the participants and how they are using the protocol. @@ -351,9 +360,10 @@ participants and how they are using the protocol. This protocol has similar goals to the [RFC 0335 HTTP Over DIDComm] protocol, but takes a lighter weight, more flexible approach. We expect that implementing HTTP over DIDComm using this protocol will be as easy as using [RFC 0335 HTTP -Over DIDComm], where the `params` data structure holds the `headers` and `body` -elements for the HTTP request. On the other hand, using the explicit [RFC 0335 -HTTP Over DIDComm] is likely a better choice if it is available and needed. +Over DIDComm], where the [JSON-RPC] request's `params` data structure holds the +`headers` and `body` elements for the HTTP request. On the other hand, using the +explicit [RFC 0335 HTTP Over DIDComm] is might be a better choice if it is +available and exactly what is needed. [RFC 0335 HTTP Over DIDComm]: /features/0335-http-over-didcomm/README.md @@ -372,8 +382,6 @@ approach is less than ideal in that: ## Unresolved questions -- [JSON-RPC] includes the concept of batch requests, where a set of [JSON-RPC] objects are included in a single request. Should we add support for batch requests to this DRPC protocol? -- [JSON-RPC] includes the concept of a "notification" request, where a response to the request is not needed. Should we add support for notification requests to this DRPC protocol? - Should we include the idea of a `request` having a goal code ([RFC 0519 Goal Codes])? [RFC 0519 Goal Codes]: /concepts/0519-goal-codes/README.md From bfa0bb23bda457a92a2a37a33b396f43ae84eb03 Mon Sep 17 00:00:00 2001 From: Stephen Curran Date: Tue, 12 Dec 2023 18:53:33 +0000 Subject: [PATCH 5/6] Update the messages to include actual JSON-RPC example Signed-off-by: Stephen Curran --- features/0804-didcomm-rpc/README.md | 45 +++++++++++++++-------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/features/0804-didcomm-rpc/README.md b/features/0804-didcomm-rpc/README.md index 7fd4224d0..fe73026bc 100644 --- a/features/0804-didcomm-rpc/README.md +++ b/features/0804-didcomm-rpc/README.md @@ -216,11 +216,11 @@ The `request` message uses the same JSON items as [JSON-RPC], skipping the `id` in favor of the existing DIDComm `@id` and thread handling. ```jsonc -{ - "@type": "https://didcomm.org/drpc/1.0/request", - "@id": "2a0ec6db-471d-42ed-84ee-f9544db9da4b", - "request" : " request" -} + { + "@type": "https://didcomm.org/drpc/1.0/request", + "@id": "2a0ec6db-471d-42ed-84ee-f9544db9da4b", + "request" : {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1} + } ``` The items in the message are as follows: @@ -252,11 +252,11 @@ protocol. ```jsonc -{ - "@type": "https://didcomm.org/drpc/1.0/response", - "@id": "63d6f6cf-b723-4eaf-874b-ae13f3e3e5c5", - "response": " response" -} + { + "@type": "https://didcomm.org/drpc/1.0/response", + "@id": "63d6f6cf-b723-4eaf-874b-ae13f3e3e5c5", + "response": {"jsonrpc": "2.0", "result": 19, "id": 1} + } ``` The items in the message are as follows: @@ -264,26 +264,29 @@ The items in the message are as follows: - `@type` -- required, must be as above - `@id` -- required, must be as defined in [RFC 0005 DIDComm] - `response` -- **required**, an item containing a [JSON-RPC] response JSON structure. - - `response` **MUST** be either single (possibly empty) [JSON-RPC] response, or an array of [JSON-RPC] requests. + - `response` **MUST** be either single (possibly empty) [JSON-RPC] response, + or an array of [JSON-RPC] responses. - If all of the [JSON-RPC] requests in the `request` message are *notifications* (e.g., the `id` item is omitted), the DIDComm `response` - message **MUST** be sent back with a value: `"response" : {}`. + message **MUST** be sent back with the value: `"response" : {}`. - Each [JSON-RPC] response **MUST** have the `jsonrpc` and `id` items, and either a `result` or `error` item. - See the [JSON-RPC] specification for details about the `jsonrpc`, `id`, `result` and `error` JSON items. As with all DIDComm messages that are not the first in a protocol instance, a `~thread` decorator **MUST** be included in the `response` message. -The special handling of the "all [JSON-RPC] requests are notifications" is to -simplify the DRPC handling to know when a DRPC protocol instance is complete. If -a `response` message is not always required, the DRPC handler would have to -inspect the `request` message to look for `id`s to determine when the protocol -completes. +The special handling of the "all [JSON-RPC] requests are notifications" +described above is to simplify the DRPC handling to know when a DRPC protocol +instance is complete. If a `response` message is not always required, the DRPC +handler would have to inspect the `request` message to look for `id`s to +determine when the protocol completes. -If the `server` does not understand how to process a [JSON-RPC] request, a `response` -error should be returned with the `error.code` value `-32601`, `error.message` -set to `Method not found`, and no `error.data` item, as per the [JSON-RPC] -specification. +If the `server` does not understand how to process a given [JSON-RPC] request, a +`response` error **SHOULD** be returned (as per the [JSON-RPC] specification) with: + +- `error.code` value `-32601`, +- `error.message` set to `Method not found`, and +- no `error.data` item. ### Constraints From 8396169d3d6b2534f15253a5d51ec7b0ea2dedb3 Mon Sep 17 00:00:00 2001 From: Stephen Curran Date: Mon, 11 Mar 2024 11:07:07 -0700 Subject: [PATCH 6/6] Add problem-report to the protocol Signed-off-by: Stephen Curran --- features/0804-didcomm-rpc/README.md | 54 ++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/features/0804-didcomm-rpc/README.md b/features/0804-didcomm-rpc/README.md index fe73026bc..14d8d7676 100644 --- a/features/0804-didcomm-rpc/README.md +++ b/features/0804-didcomm-rpc/README.md @@ -1,6 +1,6 @@ # 0804: DIDComm Remote Procedure Call (DRPC) -- Authors: [Clecio Varjao](clecio.varjao@gov.bc.ca) (BC Gov), [Stephen Curran](swcurran@cloudcompass.ca) (BC Gov) +- Authors: [Clecio Varjao](clecio.varjao@gov.bc.ca) (BC Gov), [Stephen Curran](swcurran@cloudcompass.ca) (BC Gov), [Akiff Manji](amanji@petridish.dev) (BC Gov) - Status: [PROPOSED](/README.md#proposed) - Since: 2023-11-29 - Status Note: An evolution of the HTTP over DIDComm protocol to enable an Agent to request an arbitrary service from a connected Agent and get a response. @@ -125,7 +125,7 @@ The response is likewise simple: An example of a simple [JSON-RPC] request/response pair from the specification is: -``` +```json --> {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1} <-- {"jsonrpc": "2.0", "result": 19, "id": 1} ``` @@ -170,11 +170,13 @@ The `client` agent goes through the following states: The state transition table for the `client` is: -| State / Events | Send Request | Receive Response | -| -------------- | ---------------------------------- | ------------------------------ | -| *Start* | Transition to
**request-sent** | | -| request-sent | | Transition to
**complete** | -| completed | | | +| State / Events | Send Request | Receive Response | +| ----------------------- | ---------------------------------- | ------------------------------- | +| *Start* | Transition to
**request-sent** | | +| request-sent | | Transition to
**complete** | +| completed | | | +| problem-report received | | Transition to
**abandoned** | +| abandoned | | | #### Server States @@ -185,21 +187,23 @@ The `server` agent goes through the following states: The state transition table for the `server` is: -| State / Events | Receive Request | Send Response | -| ---------------- | -------------------------------------- | ------------------------------ | -| *Start* | Transition to
**request-received** | | -| request-received | | Transition to
**complete** | -| completed | | | +| State / Events | Receive Request | Send Response or Problem Report | +| ---------------- | -------------------------------------- | ------------------------------- | +| *Start* | Transition to
**request-received** | | +| request-received | | Transition to
**complete** | +| completed | | | ### Messages The following are the messages in the DRPC protocol. The `response` message -handles all possible responses, so the `ack` ([RFC 0015 ACKs]) and -`problem-report` ([RFC 0035 Report Problem]) messages are **NOT** adopted by -this protocol. +handles all positive responses, so the `ack` ([RFC 0015 ACKs]) message is +**NOT** adopted by this protocol. The [RFC 0035 Report Problem] is adopted by +this protocol in the event that a `request` is not recognizable as a [JSON-RPC] +message and as such, a [JSON-RPC] response message cannot be created. See the +details below in the [Problem Report Message](#problem-report-message) section. -[RFC 0015 ACKs]: /features/0015-acks/README.md) -[RFC 0035 Report Problem]: /features/0035-report-problem/README.md +[RFC 0015 ACKs]: ../features/0015-acks/README.md) +[RFC 0035 Report Problem]: ../features/0035-report-problem/README.md #### Request Message @@ -245,6 +249,10 @@ processing of the request to convey the output of the processing to the `client`. As with the `request` the format mostly exactly that of a [JSON-RPC] response. +If the `request` is unrecognizable as a [JSON-RPC] message such that a +[JSON-RPC] message cannot be generated, the `server` SHOULD send a [RFC 0035 +Report Problem] message to the `client`. + It is assumed the `client` understands what the contents of the `response` message means in the context of the protocol instance. How the `client` and `server` coordinate that understanding is out of scope of this @@ -288,6 +296,18 @@ If the `server` does not understand how to process a given [JSON-RPC] request, a - `error.message` set to `Method not found`, and - no `error.data` item. +#### Problem Report Message + +A [RFC 0035 Report Problem] message **SHOULD** be sent by the `server` instead +of a `response` message only if the `request` is unrecognizable as a [JSON-RPC] message. +An [JSON-RPC] errors **MUST** be provided to the `client` by the `server` via the +`response` message, not a `problem-report`. The `client` **MUST NOT** +respond to a `response` message, even if the `response` message is not a valid +[JSON-RPC] response. This is because once the `server` sends the `response`, the +protocol is in the `completed` state (from the `server`'s perspective) and so +is subject to deletion. As such, a follow up `problem-report` message would have +an invalid `thid` (thread ID) and (at best) be thrown away by the `server`. + ### Constraints The primary constraint with this protocol is that the two parties using the