w3c / did-resolution

RELEASED DRAFT: Decentralized Identifier Resolution (DID Resolution) 0.2 Specification
https://w3c.github.io/did-resolution/
Other
17 stars 9 forks source link

DID Resolver Logic Discards DIDs with Query Strings that are not Service Endpoints #42

Closed SmithSamuelM closed 4 years ago

SmithSamuelM commented 5 years ago

This continues a conversation that started in the Hyperledger Aires WG but is more appropriate here. https://github.com/hyperledger/aries-rfcs/issues/130

In summary the current DID resolver logic as I interpret it will discard a DID that includes a Query string but is also not a DID URL with a service endpoint matrix parameter specifier.

This is incorrect. DIDs are allowed to have Query strings and not also be service endpoints.

SmithSamuelM commented 5 years ago

To clarify an ephemeral DID may not need lookup to a DID document but still must be resolved by a DID resolver should the user of the DID choose to resolve it or alternatively a multitude of ephemeral DIDs share a single DID Document. The unique ephemeral DID specific information is contained in the query.

One use case or an ephemeral DID is a derived DID (dDID) where the DID is derived using an hierarchically deterministic key chain algorithm such as BIP-44. The HDKey path could be provided in the query. A multitude of derived DIDs could then share the same DID Document. The DID resolver needs to resolve and return the DID with the query intact. The current resolver would discard the dDIDs.

SmithSamuelM commented 5 years ago

dDIDs are one way to manage keys for a large number of DIDs. The dDIDs share the same private key sequence for a root DID but each dDID is derived. This minimizes the work for the user to manage private keys (only one needs to be stored) but allows secure use of multiple dDIDs.

SmithSamuelM commented 5 years ago

Here is a reproduction of the original issue in Aries.

Potential Resolution Issues

The relevant documents on DID syntax are the DID spec itself (W3C DID Spec)[https://w3c-ccg.github.io/did-spec/] and the draft DID resolver specification (W3C DID Resolution Spec)[https://w3c-ccg.github.io/did-resolution/]

By way of background. The original design of the DID syntax and semantics included the idea that a DID could include many of the features of a URL (URI, URN). These features included path, query, and fragment components. Initially only the fragment had a specific use case where a special type of fragment component was identified called a DID Fragment (not to be confused with a generic URL fragment). The query and path were overlooked. Later discussion and pull requests repaired that by including the query and path components as formal parts of the DID ABNF. However over time the spec has evolved and now the only place that query and path show up are in ABNF is the new DID URL representation. It appears this was done to simplify the DID service endpoint resolution algorithm but some important semantics may have been lost in the process. The only use case described by the specification is for a DID that includes path, query, or fragment components is in a DID URL that includes a matrix parameter "service". The DID path and query on the DID URL would then be appended to the service endpoint url. This is both good and bad. Good because the spec does not prevent us from adding additional semantics to the query and bad because the spec may not provide insufficient guidance to implementers. Importantly this may be problematic WRT the the current DID Resolution algorithm spec. My reading of the algorithm is that it is either ambiguous or incomplete and leaves undefined some edge cases. It may be simply that I am misreading the algorithm.

The relevant clauses from the DID spec follow:

did = "did:" method-name ":" method-specific-id method-name = 1method-char method-char = %x61-7A / DIGIT method-specific-id = idchar ( ":" idchar ) idchar = ALPHA / DIGIT / "." / "-" / "" did-url = did ( ";" param ) path-abempty [ "?" query ] [ "#" fragment ] param = param-name [ "=" param-value ] param-name = 1param-char param-value = *param-char param-char = ALPHA / DIGIT / "." / "-" / "" / ":" / pct-encoded " 4.5 Path A generic DID path is identical to a URI path and MUST conform to the path-abempty ABNF rule in [RFC3986]. A DID path SHOULD be used to address resources available via a DID service endpoint. See Section § 5.6 Service Endpoints . A specific DID scheme MAY specify ABNF rules for DID paths that are more restrictive than the generic rules in this section.

4.6 Query A generic DID query is identical to a URI query and MUST conform to the query ABNF rule in [RFC3986]. A DID query SHOULD be used to address resources available via a DID service endpoint. See Section § 5.6 Service Endpoints . A specific DID scheme MAY specify ABNF rules for DID queries that are more restrictive than the generic rules in this section.

4.7 Fragment A generic DID fragment is identical to a URI fragment and MUST conform to the fragment ABNF rule in [RFC3986]. A DID fragment MUST be used only as a method-independent reference into the DID Document to identify a component of a DID Document (e.g. a unique key description). To resolve this reference, the complete DID URL including the DID fragment MUST be used as the value of the key for the target component in the DID Document object. A specific DID scheme MAY specify ABNF rules for DID fragments that are more restrictive than the generic rules in this section. It is desirable that we enable tree-based processing of DIDs that include DID fragments (which resolve directly within the DID document) to locate metadata contained directly in the DID document or the service resource given by the target URL without needing to rely on graph-based processing. Implementations SHOULD NOT prevent the use of JSON pointers ([RFC6901]). " Note that for the DID path, query only should is applied for usage in a DID URL with a service endpoint. Other usages are allowed. The DID fragment uses MUST but the use case is not sufficiently well defined and should allow other use when not the defined use case.

To be more specific, in the DID resolution spec the DID URL Resolution algorithm has a switch with 3 cases. These switches are summarized (intermediate processing steps elided) with the input conditions and resultant below. I assume that the rules are processed in order. Because the resultant actions specifies a return then I am assuming that the rule processing is aborted once a valid antecedent is reached. In other words If the antecedent is true Then the consequent is evaluated and no further rules are processed, that is, IF the antecedent is false then skip to next rule. If instead the rules are cumulative in that return does not mean return but means include in the result and all the antecedents are always checked then the rules may be valid.

A) IF the input DID URL is equal to the input DID itself: THEN Return the resolved DID Document.

Not sure how to interpret this. If the DID URL is just a valid expression for a DID then this rule will always be true even with a query, path, or fragment component. Which would mean the next two rules are not evaluated. If a DID URL with a path, query, or fragment is not equal to the DID itself then the resolver will discard the DID unless it satisfies B or C

B) IF the input DID URL contains the matrix parameter service and optionally a DID Path, DID Query, and/or DID Fragment: THEN Return the output service endpoint URL.

C) IF the input DID URL contains a DID Fragment::THEN Return the output resource. (JSON-LD object whose id property matches the input DID URL)

This seems to be too greedy as it does not allow for JasonP or resolution into the DID document. Not all fragments correspond to an id property. This seems to be problematic no matter the definition.

Semantics

In a conventional URL the path component may be empty. The path component, consists of a sequence of path segments separated by a slash (/). In a conventional URL (Not DID Url) a path is ALWAYS defined for a URI, though the defined path may be empty (zero length). When the path is empty there is some default resource that is ALWAYS provided. This is not the case for a DID URL that is when a path component is missing there is no defined default resource unless the DID URL includes a service matrix parameter. Then the default resource is provided by the service endpoint.

I suggest that there is a valid default resource that could be defined for a DID URL for all other cases except when the DID URL includes a service matrix parameter. That default would be the did document itself. This is consistent with the precedent set by the DID Fragment specification where the fragment resolves to an object within the DID document. To be consistent with the conventional URL syntax, a default path component in a DID URL would also ALWAYS be defined. The semantic is as follows: WHEN the DID includes a service matrix parameter THEN the default path is given by the service endpoint resolution algorithm OTHERWISE the default path resolves to the DID itself its meta-data from the DID Document. The resolution of a non-empty path ie no default would be method dependent

Likewise the semantics of DID query could also be defined: When the DID includes a service matrix parameter THEN the DID query is applied to the service endpoint. Otherwise the did query is applied to the resource specified by the path. When the path is empty then the default path which would be DID itself and its metadata from the DID document.

In the conventional URL usage, a query string modifies the resource specified by the URL. Originally the main use case was to provide the data values for the fields belonging to a form resource. This usage is evocative of the proposed use herein of providing the field values for a key material authentication block associated with the DID as a resource.

What remains then is to specify what the query parameters should be.

I suggest mimicking the field names from the Authentication block.

{ "id": "did:example:123456789abcdefghi#keys-2", "type": "Ed25519VerificationKey2018", "controller": "did:example:123456789abcdefghi", "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" } maybe put auth in front such as

did:example:12345678abcees?auth_type=Ed25519VerificationKey2018

another would be an expiration date which would force a did document resolution to get the most recent authentication block

did:example:12345678abcees?auth_type=Ed25519VerificationKey2018&auth_expires=20190712

TODO:

Clarify DID URL Resolution algorithm

Define Fields

Update associated specifications

Another use case of the DID query is for Hierarchically Deterministic Keychains. The Query string can include the derivation path for say a BIP-44 derived did. This is described in this paper:

https://github.com/WebOfTrustInfo/rwot6-santabarbara/blob/master/final-documents/DecentralizedAutonomicData.pdf

These now are two cogent use cases for the DID Query for some important purpose other than modifying a service endpoint.

SmithSamuelM commented 5 years ago

Tested against universal resolver and it discards DIDs with query strings

See https://github.com/decentralized-identity/universal-resolver/issues/42

peacekeeper commented 5 years ago

I fully agree with you that DID URLs with query strings (and without service matrix parameter) should also be dereferencable and not be discarded. It's however not quite clear to me yet what they dereference to. Perhaps the answer is simply that it's method- or application-specific.

We need to figure out how to improve the (currently very early) DID URL Dereferencing algorithm in the spec to make this work.

Let's make this a topic on one of the upcoming DID calls: https://docs.google.com/document/d/1qYBaXQMUoB86Alquu7WBtWOxsS8SMhp1fioYKEGCabE/

peacekeeper commented 5 years ago

Tested against universal resolver and it discards DIDs with query strings

See decentralized-identity/universal-resolver#42

As I commented on the other issue, this may have been due to a typo you had in your DID URL.

peacekeeper commented 4 years ago

@SmithSamuelM do you think we can close this now after #47 has been reviewed and merged?

SmithSamuelM commented 4 years ago

Yes