Skip to content

Latest commit

 

History

History
187 lines (122 loc) · 12.3 KB

File metadata and controls

187 lines (122 loc) · 12.3 KB

0335: HTTP Over DIDComm

  • Authors: Filip Burlacu (SecureKey)
  • Status: PROPOSED
  • Since: 2019-12-03
  • Status Note: implementation is being explored by SecureKey
  • Supersedes:
  • Start Date: 2019-11-26
  • Tags: feature, protocol

Summary

Allows HTTP traffic to be routed over a DIDComm channel, so applications built to communicate over HTTP can make use of DID-based communication.

Motivation

This protocol allows a client-server system that doesn't use DIDs or DIDComm to piggyback on top of a DID-based infrastructure, gaining the benefits of DIDs by using agents as HTTP proxies.

Example use case: Carl wants to apply for a car loan from his friendly neighborhood used car dealer. The dealer wants a proof of his financial stability from his bank, but he doesn't want to expose the identity of his bank, and his bank doesn't want to develop a custom in-house system (using DIDs) for anonymity. HTTP over DIDComm allows Carl to introduce his car dealer to his bank, using Aries agents and protocols, while all they need to do is install a standard agent to carry arbitrary HTTP messages.

HTTP over DIDComm turns a dev + ops problem, of redesigning and deploying your server and client to use DID communication, into an ops problem - deploying Aries infrastructure in front of your server and to your clients.

Tutorial

Name and Version

This is the HTTP over DIDComm protocol. It is uniquely identified by the URI:

"https://didcomm.org/http-over-didcomm/1.0"

Concepts

This RFC assumes that you are familiar with DID communication, and the ~purpose decorator.

This protocol introduces a new message type which carries an HTTP message, and a method by which an Aries agent can serve as an HTTP proxy. The Aries agent determines the target agent to route the HTTP message through (for example, by parsing the HTTP message's request target), and when the target agent receives the message, it serves the message over HTTP.

The specifics of determining the target agent or route are not part of this specification, allowing room for a wide array of uses:

  • A network of enterprise servers behind agents, with the agents being a known, managed pool, with message routing controlled by business logic.
  • A privacy mix network, with in-browser agents making requests, and routing agents sending messages on random walks through the network until an agent serves the request over the public internet.
  • A network of service providers behind a routing network, accessed by clients, with any provider able to handle the same class of requests, so routing is based on efficiency/load.
  • A network of service providers behind a routing network, accessed by clients, where the routing network hides the identity of the service provider and client from each other.

Protocol Flow

This protocol takes an HTTP request-response loop and stretches it out across DIDComm, with agents in the middle serving as DIDComm relays, passing along messages.

The entities involved in this protocol are as follows:

  • The client and server: the HTTP client and server, which could communicate via HTTP, but in this protocol communicate over DIDComm.
  • The client agent: the aries agent which receives the HTTP request from the client, and converts it to a DIDComm message, which it sends to the server agent, and translates the reply from the server agent into an HTTP response.
  • The server agent: the aries agent which receives the DIDComm request message from the client agent, creates an HTTP request for the server, receives the HTTP response, and translates it into a DIDComm message which it sends to the client agent.

HTTP client and server communicate over DIDComm

Before a message can be sent, the server must register with its agent using the ~purpose decorator, registering on the scheme://host:port/path prefix of the each request URI it wishes to serve.

When a client sends an HTTP request to a client agent, the agent may need to maintain an open connection, or store a record of the client's identity/IP address, so the client can receive the coming response.

The client agent can include some logic to decide whether to send the message, and may need to include some logic to decide where to route the message (note that in some architectures, another agent along the route makes the decision, so the agent might always send to the same target). If it does, it constructs a request DIDComm message (defined below) and sends it to the chosen server agent.

The route taken by the DIDComm message between the client and server agents is not covered by this RFC.

The server agent receives the request DIDComm message. It can include some logic to decide whether to permit the message to continue to the server. If so, it makes an HTTP request using the data in the request DIDComm message, and sends it to the server.

Note: in some use-cases, it might make sense for the server agent to act as a transparent proxy, so the server thinks its talking directly to the client, while in others it might make sense to override client identity information so the server thinks it's connecting to the server agent, for example, as a gateway. In this case, the client agent could anonymize the request, rather than leaving it up to the server agent.

This same anonymization can be done in the other direction as well.

The communication happens in reverse when the server sends an HTTP response to its agent, which may again decide whether to permit it to continue. If so, the contents of the HTTP response are encoded into a response DIDComm message (defined below), sent to the client agent, which also makes a go/no-go decision, does some logic (for example, looking up its thread-id to client database) to figure out where the original request in this thread came from, encodes the response data into an HTTP response, and sends that response to the client.

Message Format

DIDComm messages for this protocol look as follows:

request
{
  "@type": "https://didcomm.org/http-over-didcomm/1.0/request",
  "@id": "2a0ec6db-471d-42ed-84ee-f9544db9da4b",
  "~purpose": [<partial resource uri: scheme://userinfo@host:port/path>],
  "method": <method>,
  "resource-uri": <resource uri value>,
  "version": <version>,
  "headers": [],
  ["body": b64enc(body)]
}

The purpose decorator contains at least one element, which is the prefix of the resource URI string, up until the path (inclusive) and excluding any query or fragment.

response
{
  "@type": "https://didcomm.org/http-over-didcomm/1.0/response",
  "@id": "63d6f6cf-b723-4eaf-874b-ae13f3e3e5c5",
  "~thread": {
    "thid": "2a0ec6db-471d-42ed-84ee-f9544db9da4b",
    "sender_order": 1
  },
  "status": {
      "code":"",
      "string":""
  },
  "version": "",
  "headers": [],
  ["body": b64enc(body)]
}

Responses need to indicate their target - the client who sent the request. Response DIDComm messages must include a ~thread decorator so the client agent can correlate thread IDs with its stored HTTP connections.

Receiving HTTP Messages Over DIDComm

Aries agents intended to receive HTTP-over-DIDComm messages have many options for how they handle them, with configuration dependent on intended use. For example:

  • Serve the message over the internet, configured to use a DNS, etc.
  • Send the message to a specific server, set in configuration, for an enterprise system where a single server is behind an agent.

Reference

Determining the recipient DID by the Resource URI

In an instance of the HTTP over DIDComm protocol, it is assumed that the client agent has the necessary information to be able to determine the DID of the server agent based on the resource-uri provided in the request. It's reasonable to implement a configuration API to allow a sender or administrator to specify the DID to be used for a particular URI.

-Alive & Timeout

The client agent should respect the timeout parameter provided in a keep-alive header if the request header is a keep-alive connection.

If a client making an HTTP request expects a response over the same HTTP connection, its agent should keep this connection alive while it awaits a DIDComm response from the server agent, which it should recognize by the ~thread decorator in the response message. Timing information can be provided in an optional ~timing decorator.

Agents implementing this RFC can make use of the ~transport decorator to enable response along the same transport.

When the Client Agent is the Server Agent

There is a degenerate case of this protocol where the client and server agents are the same agent. In this case, instead of constructing DIDComm messages, sending them to yourself, and then unpacking them, it would be reasonable to take incoming HTTP messages, apply any pre-send logic (filtering, etc), apply any post-receive logic, and then send them out over HTTP, as a simple proxy.

To support this optimization/simplification, the client agent should recognize if the recipient DID is its own, after determining the DID from the resource URI.

HTTP Error Codes

Failures within the DIDComm protocol can inform the status code returned to the client.

If the client agent waits for the time specified in the request keep-alive timeout field, it should respond with a standard 504 gateway timeout status.

Error codes which are returned by the server will be transported over DIDComm as normal.

Why HTTP/1.x?

The protocol carries HTTP/1(.x) messages for a few reasons:

  • Wire-level benefits of HTTP/2 are lost by wrapping in DIDComm and sending over another transport (which could itself be HTTP/2)
  • DIDComm is not, generally, intended to be a streaming or latency-critical transport layer, so HTTP responses, for example, can be sent complete, including their bodies, instead of being split into frames which are sent over DIDComm separately.

Drawbacks

You might find the cost too high, with wrapping your messages into HTTP messages, and then wrapping those into DIDComm envelopes. This cost includes the time it takes to wrap and unwrap payloads, as well as the increase in message size. Small messages and simple formats would benefit from being encoded as JSON payloads within custom DIDComm message formats, instead of being wrapped in HTTP messages within DIDComm messages. Large data might benefit from being sent over another channel, encrypted, with identification, decryption, and authentication information sent over DIDComm.

Rationale and alternatives

The main alternative to the method proposed in this RFC is to implement DIDComm in your non-DIDComm applications, if you want them to be able to communicate with each other over DIDComm.

Prior art

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.

Unresolved questions

  • What parts of the design do you expect to resolve through the enhancement proposal process before this gets merged?
    • Likely some specifics of go/no-go or routing logic
  • What parts of the design do you expect to resolve through the implementation of this feature before stabilization?
    • The routing and logic specifics of certain use cases
  • What related issues do you consider out of scope for this proposal that could be addressed in the future independently of the solution that comes out of this doc?

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.

Name / Link Implementation Notes

|