Skip to content
This repository has been archived by the owner on Oct 29, 2019. It is now read-only.

Inconsistent ABNF and related definitions #170

Closed
jandrieu opened this issue Feb 16, 2019 · 52 comments · Fixed by #189
Closed

Inconsistent ABNF and related definitions #170

jandrieu opened this issue Feb 16, 2019 · 52 comments · Fixed by #189
Labels
discuss Wider discussion in an issue or meeting required before merging

Comments

@jandrieu
Copy link
Contributor

jandrieu commented Feb 16, 2019

TLDR: The ABNF and related logical elements of a DID are inconsistently defined.

The current pull request refactoring the ABNF rules does not address the issue I'm raising here. #168

My first point is that the charter isn't about defining a DID reference. It's about defining a DID. The current spec defines a DID as merely a component in a DID reference.

My second point is that a DID should include the entirety of the string that is presented, just like a URL includes the query part and and fragment part. https://tools.ietf.org/html/rfc3986 The current spec, with its definition of a DID as a component in a did-reference, a URI of the following form would NOT be a DID per the spec:

did:example:123456789abcdefghi#keys-1

Per the current spec (and the PR) this would be a DID-reference, not a DID. Only the first part is a DID. This is stated explicitly:

The generic DID scheme is a URI scheme conformant with [RFC3986]. It consists of a DID followed
by an optional path and/or fragment. The term DID refers only to the identifier conforming to the
did rule in the ABNF below
; when used alone, it does not include a path or fragment. A DID that
may optionally include a path and/or fragment is called a DID reference.

Even if one would prefer to follow the notion that the DID is "only the identifier", then this statement might be correct if rewritten as

The generic DID-reference scheme is a URI scheme conformant with [RFC3986]. It consists of a
DID followed by an optional path and/or fragment.

However, this seems inconsistent with the last statement in that paragraph:

A DID that may optionally include a path and/or fragment is called a DID reference.

This sentence is logically impossible. A "DID" that includes a path or fragment is NOT a DID. It is a did-reference. It is that, not that it is called that. Further, by the previous statements, DIDs may not optionally include a path and/or fragment.

This is also out of sync with current consensus in the way we speak of DIDs. As illustrated in the last paragraph, we consistently refer to did-references as DIDs. From Section 4.3:

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.

Again, if "DIDs" can contain DID fragments, then by the above (problematic) language and the ABNF, that "DID" is actually a DID reference which by definition can't be true given the current ABNF.

My third point is that the did-reference spec looks like the URI spec, but is fundamentally different.
From the current spec:

did-reference      = did [ "/" did-path ] [ "#" did-fragment ]
did                = "did:" method ":" specific-idstring

However, this is significantly different from the generic URI syntax (RFC3986)

URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]

And further breaks with this URI-reference spec in RFC3986. It makes DID-references something other than URI-references, which makes DIDs something other than URIs.

URI-reference = URI / relative-ref

A URI-reference is either a URI, or a relative-ref and a relative-ref has the following syntax:

      relative-ref  = relative-part [ "?" query ] [ "#" fragment ]

      relative-part = "//" authority path-abempty
                    / path-absolute
                    / path-noscheme
                    / path-empty

If we attempt to follow that pattern more closely (yet combining the query & fragment parts to remove redundancy), I propose:

did = "did:" method specific-idstring relative-part 
method             = 1*methodchar
methodchar         = %x61-7A / DIGIT
specific-idstring  = idstring *( ":" idstring )
idstring           = 1*idchar
idchar             = ALPHA / DIGIT / "." / "-"
relative-part = path-part [ "?" query] [ "#" fragment ]
path-part = / path-absolute
                    / path-empty
did-reference = DID / relative-part

[Yes, this is incomplete. I leave query and fragment as an exercise for the editors. Pull them in from the RFC3986]

With this definition, a DID-reference is a URI-reference where the query term is the name of a service used for endpoint discovery by the user-agent. It is aligned with how URI-references are used. This implies that fragments should NOT be used to indicate dereferencing a DID to the resource at the end of a service endpoint, but rather to refer to the element itself (within the DID Document). Only the query term is interpreted as implying the further dereference.

Unfortunately, if service (from did-spec) is reasonably replaced with query (from the URI spec), then we still have the question of what the path part does. The current spec says

A DID path SHOULD be used to address resources available via a DID service endpoint.

If I follow the ideas of Sam Smith and DADs, then the path part would allow hierarchical indexing to provide resolution to an subset of a DID Document rather than the root of the DID Document. This would be a distinct from the query/service component which is for discovering the named service endpoint for a given DID id/path reference. Which is to say, I think this remains a point of significant ambiguity in the feature space (what is the path part)--and not just a grammatical error. I'm not sure I have a recommendation in this area. I don't know of any implementations that use such hierarchies other than what I recall from DADs--and I believe those may be addresses on a method-specific basis with colon ":" delimited identifiers.

Additionally, the section on fragments has this gem:

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.

This paragraph is ambiguous as to whether or not a fragment is a reference within the context of the document, as suggested by " (which resolve directly within the DID document)" or if it can reference something within the service endpoint, as suggested by "to locate metadata contained directly
in the DID document or the service resource". I take this to mean that if the DID-reference (aka DID) contains a service (aka query), then any fragment reference is to be appended to the service endpoint for dereferencing in the context of that service endpoint. I can see the appeal of this. However, it presumes a certain understanding and stability of the structure of the named endpoint and could easily result in an invalid URI if the service endpoint already has a fragment. Further, it is doubly ambiguous when a fragment is used to refer to a service endpoint, as seems to be the proposal in the PR.

Rather, I would use the query part to look up the service, and when dereferencing the service endpoint, and then applying the fragment in the context of the dereferenced endpoint at lease uses a valid URL (just one fragment).

For example, using Example 8 from the spec https://w3c-ccg.github.io/did-spec/#example-8-various-service-endpoints

"service": [{
    "id": "did:example:123456789abcdefghi;openid",
    "type": "OpenIdConnectVersion1.0Service",
    "serviceEndpoint": "https://openid.example.com/"
  },

A relative part (query and fragment) of ?did:example:123456789abcdefghi;openid would dereference to the open id endpoint.

This is different from both the current spec--with its ambiguity around what the ";" is for (it is in the service section but not in the ABNF). And the PR mentioned above, which creates some new elements, which IMO are unnecessary and confusing as well as using fragments to refer to services.

Further, the current spec and proposed PR both use absolute URIs for service endpoint ids, but the PR says "the service path [is] a URI path and MUST conform to the ABNF of the path-rootless ABNF
rule in [[RFC3986]]" Unfortunately, this is logically impossible. It is either a URI path (which can be a path-abempty, path-absolute, path-noscheme, path-rootless, or path-empty), or it is a path-rootless.

I may have mis-parsed the ABNF, but the current use of the service endpoints is inconsistent with how fragments work in other URIs, especially in URLs. For the sake of this example, let's revisit the above example (from Section 8. Examples) and just focus on the id of the first service endpoint:

"id": "did:example:123456789abcdefghi;openid"

which, in the PR is changed to

"id": "did:example:123456789abcdefghi#openid"

If we were to use a standard URL to refer to an element with that id in an HTML page (http://example.com), we would use either the absolute URL
http://example.com#did:example:123456789abcdefghi;openid
from the spec, or
http://example.com#did:example:123456789abcdefghi#openid
from the PR.

If we apply that pattern to a service identifier in the DID Document resolved by did:example:123456789abcdefghi, then the analogous URL would be
did:example:123456789abcdefghi#did:example:123456789abcdefghi;openid
for the original spec and
did:example:123456789abcdefghi#did:example:123456789abcdefghi#openid
for the PR.

Unfortunately, these PR URIs are invalid, because they contain two fragments, and all four are unnecessarily redundant.

In contrast, what I believe is the desired original DID is something like

did:example:123456789abcdefghi#openid

Which would refer to the openid service endpoint declaration in the DID Document and, based on my proposal,

did:example:123456789abcdefghi?openid

Would actually dereference the service at the endpoint.

This is not only a valid URI, it's concise and straightforward.
In order to have that URI be consistent with how other URI fragments map to the ids in a document,
the service endpoint should in the example 8 should be:

"service": [{
    "id": "openid",
    "type": "OpenIdConnectVersion1.0Service",
    "serviceEndpoint": "https://openid.example.com/"
  },

My comments therefore are in two parts:

  1. The grammar of the current ABNF is inconsistent with itself, with URIs, and with how we talk about DIDs. This lack of rigor is especially problematic in ABNF which is there precisely to be rigorous because the rest of the document suffers from the inherent ambiguity in human language.
  2. The logic of the current DID components are inconsistent with their similarly named parts in the URI spec. I propose that "path", "query", and "fragment" are better terms if they have slightly different definitions:
    a. path: like a URI path, a hierarchical index into the DID document
    b. query: the name of a service endpoint for discovery (and eventual dereferencing)
    c. fragment: a named index into the DID document, hierarchically constrained by the path
  3. Seems like a the query part should follow RFC3986 def of queries, not path-rootless.

My apologies this is so long.

I'd like @burnburn and @ChristopherA to comment on this.

@talltree
Copy link
Contributor

talltree commented Feb 17, 2019 via email

@jandrieu
Copy link
Contributor Author

A few questions, as I want to understand the motivation for the extra complexity I'm seeing.

First, you didn't respond to my surprise that

did:example:123456789abcdefghi#keys-1

Is, in fact, not a DID by your definition. This is extremely strange to me and I'm struggling to understand the motivation.

If this were transposed to be a url:

http://example.com/123456789abcdefghi#keys-1

Then this URL would be called a URL, as would

http://example.com/123456789abcdefghi

The URL is the entire string, including the query and fragment part. This is also true of the generic URI definition, and especially relevant in the context of assertions that DIDs are URIs, URLs, and sometimes act like URNs.

Why break that pattern?

To me the DID has always been the whole thing. Maybe that's because I've been focused on the user side of things and not reading the spec clearly, but I think we'll run into a lot of confusion across the W3C if the syntax for DIDs is so different from URIs and URLs.

Second is that I don't understand what you are trying to do with the query & fragment parts.

My final point is that the treatment of DID service URLs (*did-service-ref *in the ABNF above) is very carefully designed not to interfere with the use of a normal path, query, or fragment on a URL—that's why we specify the service-id component to be part of the hier-part rule. It forces percent-encoding of the service ID string in a DID document (if that string is a URL) so that it doesn't contain any character not allowed in a hier-part—that's what avoids double queries or double fragments.

By my understanding (and current re-read of the relevant sections of 3986), both query parts and fragment parts are percent-encoded with the exception of "/" and "?".

Could you help me understand what you're trying for here? After a few readings, it seems like you want to somehow embed a URL in the DID, when there really isn't any need to do that (there's no need for service ids to be URLs, especially when there is a service type, and a service endpoint, which probably is a URL). And if you really want it to be a URL, you can escape it.

Both the did-service-ref and did-fragment ref can contain fragments, but did-fragments can't contain queries, which seems odd. And by the above definition, I'm fairly sure the did-fragment-ref is not a valid uri-reference because it excluded queries. In fact, the did-relative-ref still includes the DID, making it not very relative at all.

In my attempt to map DIDs to URIs, using the same structure you started with

URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]

I agree, all we need to do is customize the hier-part. But your proposal sticks the fragment part into the hier-part asymmetrically in two newly defined terms (did-service-ref and did-fragment-ref), one with a query part and one without, so I'm not seeing the continuity with URIs.

Note that the URI hier-part is

      hier-part   = "//" authority path-abempty
                  / path-absolute
                  / path-rootless
                  / path-empty

Consider the following ABNF, I believe you get good DIDs with the single quirk of how I would like to propose we handle service differently.

did = "did:" hier-part [ "?" query ] [ "#" fragment ]
hier-part   = authority path
path = path-abempty / path-absolute  / path-rootless  / path-empty
authority = method ":" method-specific-idstring 
method = 1*methodchar 
methodchar = %x61-7A / DIGIT 
method-specific-idstring = idstring *( ":" idstring ) 
idstring = 1*idchar idchar = ALPHA / DIGIT / "." / "-"*

the following are to be included from RFC3986

  • path-abempty
  • path-absolute
  • path-rootless
  • path-empty
  • query
  • fragment

In short, the authority is just the method and the id string, and we use the query for dereferencing services, and with one additional exception, is URI compatible. What's not handled in this ABNF (and handled incorrectly, I believe, in yours) is the relative-ref.

It shouldn't be too hard, but we might do well to sync up on what a relative DID looks like.
I think we agree the following is an absolute DID (or did-reference or something)

did:example:123456789abcdefghi

And if we are in the DID Document associated with that DID, then the absolute DID

did:example:123456789abcdefghi#openid

and the relative DID

#openid

would refer to the same element, correct? If so, then we need a relative definition that supports that. Neither yours nor mine does that.

I guess the only trick is to know that relative URIs within a DID Document are presumed to be relative DIDs, not relative URIs. I think this is mostly a non-issue for relative fragments, but for relative paths, it's gets trickier, depending on the semantic meaning of a path wrt the DID Document. (A relative URL in an html page is likely to trigger another GET unless you have a client-side router in a single-page app.)

The quirk of my proposal--which is new to the community so I doubt anyone else has thought of it this way--is simply to use the query part to specify the service id and to dereference DIDs that have a query by dereferencing the service endpoint, while all other dereferencing returns the DID Document (or a portion thereof depending on what paths are supposed to be used for).

Fragments should still work as normal, so if we have the following two DIDs

did:example:123456789abcdefghi#openid
did:example:123456789abcdefghi?openid

Then the first returns the JSON of the service endpoint. Or more likely, the user-agent dereferences http://example.com/123456789abcdefghi and then returns/displays/focuses/scrolls to the service endpoint definition.
The second dereferences the openid service endpoint directly.
In short, use fragments to refer to an element with an "id" property, and use a query to activate a service endpoint.

It seems to me updating the authority part as above and interpreting the query part as described, we have a much simpler ABNF that has all the features we need in a DID with MUCH greater alignment with URIs.

Further questions to help me understand the semantics:

  • Is there any other use of the query part by implementations?
  • Similarly, how are paths actually being used?

A final note: it seems there are a few too many * asterisks in your ABNF. I wasn't quite sure what you were trying to do there unless you meant to trigger markdown formatting.

@dhh1128
Copy link
Contributor

dhh1128 commented Feb 19, 2019

FWIW, I am astonished that anybody would think did:xyz:abc123#key-1 IS a DID. I always thought it was a reference to something in a DID doc, but only the part before # was the DID. The DID method specs that I have studied only contemplate the part before the fragment as a DID--with the fragment part being defined separately. Or are we saying that every method spec can define fragment semantics as well?

@dhh1128
Copy link
Contributor

dhh1128 commented Feb 19, 2019

What @jandrieu mentions about the logical inconsistency of absolute DID references vs. relative ones is discussed in Issue #97 as well. I don't feel like that issue has ever been resolved.

@talltree
Copy link
Contributor

talltree commented Feb 19, 2019 via email

@dmitrizagidulin
Copy link

Ok, this issue brings up a lot of excellent points. Let me see if I can address them, in the context of that pending PR.

@dmitrizagidulin
Copy link

OK, so let's start with your fundamental objection:

@jandrieu : My first point is that the charter isn't about defining a DID reference. It's about defining a DID. The current spec defines a DID as merely a component in a DID reference.

Yes, that's true. The charter is about defining a DID. But in order for the spec to be at all useful, we also need to talk about the two main things that DIDs are for.

To put it another way: DIDs resolve to DID Docs, which are containers for two main things. 1) cryptographic material (such as keys or other stuff for proofs), and 2) Service endpoints. So we kind of have to at least mention ways to refer to those keys, and to refer to those endpoints. And that's what DID References are.

To put it another way: yes, we could move any and all discussion (including the ABNF rules) for DID Reference URLs to the DID Resolution spec. But I strongly believe that doing so would be a disservice to implementers.

The current spec, with its definition of a DID as a component in a did-reference, a URI of the following form would NOT be a DID per the spec: did:example:123456789abcdefghi#keys-1

I would echo @dhh1128 in saying -- that is correct, and on purpose.

So for example, https://example.com/page.html is a URI for a web page. And https://example.com/page.html#Contact is a URI for a section of that page. (But not the page itself.) So, both of those things are URIs. But one is a URI for a page, and the other is for a section.

So similarly, did:example:123456789abcdefghi is a URI for a DID.

But did:example:123456789abcdefghi#keys-1 is a URI for a key, that happens to live inside that DID. So again, both things are URIs. But the second thing is not a DID URI.

I'm'a pause here - does this make sense so far?

@jandrieu
Copy link
Contributor Author

FWIW, I am astonished that anybody would think did:xyz:abc123#key-1 IS a DID.
Indeed. I appear to be in a minority, but I think my perspective is what most tech-savvy newbies-to-DIDs are going to have when DIDs are presented as URIs or URLs.

If there were a field on a web page where you enter a DID, would you be able to enter did:xyz:abc123#key-1? Or would that be rejected as improper syntax? (It would by the current ABNF, but I don't think it should be).

Even in the background, if an API had a parameter that is a DID, would your wallet put did:xyz:abc123#key-1 into that parameter?

Possibly not with fragments. For URLs, fragmets are managed by the user-agent and not sent to the server, so you might need to distinguish the interaction to answer that question.

However, if the that DID had a path or a query part instead of a fragment e.g., did:xyz:abc123?openid, wouldn't the wallet provide that entire string to the API?

Or more to the point, if I have a business card with a DID as with my secure email endpoint
did:xyz:abc123?smail, isn't the entire string what someone would, ideally, be able to put into a DID compatible browser and have it just work?

I'll speak to the query thing in a separate note.

My strong sense is that it is the branded name, "DID" that we want the most leverage from. If we want people to thing of that as a URI, then it should almost certainly include the entire string. If, instead, we want the most important thing to be NOT like a URI, but be limited to just the method and id-string, then we should definitely stop talking about it as a URI.

To wit, at the December W3C workshop on strong authentication and identity, a colleague challenged me that DIDs are NOT URLs. We had a polite back and forth and pulled up RFC3986 and there was some reasonable debate. This will continue to happen if we talk about just the hier-part as that is the DID, while ascribing to it all the benefits of a DID-URL. That will confuse people to no end, especially those who have literally spent years debating and teasing out exactly what URIs and URLs and URNs actually are.

@dmitrizagidulin
Copy link

dmitrizagidulin commented Feb 19, 2019

If there were a field on a web page where you enter a DID, would you be able to enter did:xyz:abc123#key-1?

Depends on if that particular client (on that web page) supported it. If it did, what you would get back is NOT a DID document, but a key object.

Even in the background, if an API had a parameter that is a DID, would your wallet put did:xyz:abc123#key-1 into that parameter?

No, it would not. The wallet would only use that string in an API call that expected a key URI.

My strong sense is that it is the branded name, "DID" that we want the most leverage from.

Sure, I totally agree and get that -- branding and naming is important. We should definitely continue the discussion on what we're gonna name things.
I just want to start with an overall consensus that we're talking about two different things (in fact, at least 3 different things).

Thing one: A URI that resolves to a DID document. What should that be named? #168 calls it a "DID", or a DID URI.

Things two: A URI that refers to sections inside the DID document, such as keys. What should we call that? (#168 currently calls it a "DID Fragment Reference".

Thing three: A URI of the form <did>;<service id>/service-path?service=query#service-fragment, which resolves the service endpoint URL from the did document, then passes service-path, service-query and service-fragment to that resolved endpoint. The PR currently calls this a "DID Service Reference".

Can we agree that those are three different things?

did:xyz:abc123#key-1 <- this resolves to a key.

did:xyz:abc123;smail/messages/1#title <- this resolves to whatever lives in the service endpoint that has the id smail, the service path /messages/1, service fragment title.

@dmitrizagidulin
Copy link

dmitrizagidulin commented Feb 19, 2019

In fact, for completeness, let's throw in resolvers into there, as well. Here's our complete bestiary of URIs that we're talking about on CCG calls.

1) https://resolver.example.com/v0?get_did=did:xyz:abc123&gzip=true#alfjalkfjaljd

This is a plain HTTPS URI that is passed to a resolver. Not a DID URI in any way, even though it happens to resolve to a DID Document. There are two query params, get_did and gzip, that are passed to the resolver service. Additionally, to refer to what @jonnycrunch mentioned about IPFS URIs, the uri fragment alfjalkfjaljd is used on the client-side to decrypt the results.

2) did:xyz:abc123

This is a DID URI, conforming to the ABNF rule from the did spec. It resolves to a DID Document. Now, a resolver library might translate it to a resolver URI above, or might be able to fetch it directly.

3) did:xyz:abc123#zopqrs

This is a URI that resolves to a key object. The semantics are "fetch the DID document. then find a linked data node with the id did:xyz:abv123#zopqrs", which will most likely be a key, so return that.

4) did:xyz:abc123/some/path

No-op. This is a URI that has no semantics, at the moment (though @msporny is arguing that it should be included in the ABNF, for future use). It means "fetch the DID document, then pass the path /some/path to it, but since there's no server on the other end and no semantics defined for this, nothing happens."

This is different from a service URI with a path, see below.

5) did:xyz:abc123?query_key=value

No-op. This is also a URI that has no semantics at the moment (same as 4). Again, different from a service reference uri that has a query fragment.

6) did:xyz:abc123;smail

This is a URI with the semantics "fetch the DID Doc, find a serviceEndpoint referenced by did:xyz:abc123#smail, and then pass along the empty service-path to it, /, see what happens.

7) did:xyz:abc123;smail/messages/1?summary=true#title

This is a URI with the semantics "fetch the DID Doc, find a serviceEndpoint referenced by did:xyz:abc123#smail, then make a call to it with the following parameters: service-path of /messages/1, service query summary=true, and then also feel free to use the service fragment title on the client side.

@ChristopherA
Copy link
Contributor

If there were a field on a web page where you enter a DID, would you be able to enter did:xyz:abc123#key-1?

My problem with this example is that a parallel web browser comparison is that the browser gets the entire contents of the web page dereferenced at http://xyz.abc123 but then IT is responsible for displaying #key-1 if it can, and there are a number of browsers and webapps that do not support that and it is perfectly fine for them to do so.

So if key-1 is a fundamental operation that should dereference to a key, it should not use #. If it is the apps responsibility to parse the DID Document and itself use the hint of key#1 to find it, then # is appropriate.

@jandrieu
Copy link
Contributor Author

@ChristopherA yes. that's right, but in the widget that you enter the DID, you include the fragment.

My point is that anywhere someone expects to be able to put a DID, they are going to expect to also put whatever query, path, and fragment parts their use case requires.

Whatever the current implementers and editors think a DID should be, if its discussed as a new kind of URL--which we have said at the beginning of every presentation I've seen--then people are going to include all of those parts in their idea of what a DID is.

@talltree
Copy link
Contributor

talltree commented Feb 20, 2019 via email

@jandrieu
Copy link
Contributor Author

jandrieu commented Feb 20, 2019

@dmitrizagidulin Thanks for the detailed response. The examples you give help considerably.

However, there are some core misconceptions in some of your points.

First, all DID resolve to the DID Document. That's the first step in dereferencing. Not all dereferencing returns the DID Document. So, your three things above are not consistent with the meaning of the terms as defined in RFC3986. If you mean that some DIDs dereference to the DID Document while others dereference to a service endpoint, I'm in agreement. How paths and fragment affect that is another matter. Paths should, arguably, affect the scope of the resource returned, while fragments generally are sent to neither the resolver nor the resource store upon dereferencing, but rather applied to the resource after dereferencing.

Second, URIs are not defined by what they return. We don't have jpeg URIs or html URIs or key URIs. Rather, they are defined by the protocol used for resolving and dereferencing. We do have http URIs and telnet URIs. In fact, it is impossible to know with HTTP URIs what type of resource will be returned. There is a negotiation step in the headers where user-agents indicate their preference for various return types, e.g., asking for JSON or HTML or txt. The server may or may not pay any attention to that header.

And now we have a DID URI. Which, barring the name conflation that's been proposed, is just a DID, which is a URI. There is no such thing as a DID Document URI or a key URI. That's a category error.

http://example.com is an URI for HTTP
did:example:xyz is a URI for a DID
http://example.com?q=bob#definition is a URI for HTTP
and, I argue,
did:example:xyz?q=bob#definition should also be a URI for a DID

The introduction of a "DID URI" as the fully expressed DID with path, query, and fragment parts is a weird misnomer that is inconsistent with other URIs, like HTTP URIs, FTP URIs, etc. Those specs don't defined "HTTP URIs" or "FTP URIs" they define URIs for http and for ftp. And what we are defining is a URI for DIDs. That's a single thing, a single spec, not a DID and separately a DID URI.

No one is going to understand us if we try to tell them differently. As I pointed out above, there are numerous examples in the spec where it says things like "DIDs with optional fragments", clearly referring to did:example:xys#definition as a DID.

You could argue that the right fix is to update the spec to be more rigorous. Yes. We should do that. We should also be like water and flow with the usage that people in this community have already internalized. Clearly, even some of those who hold on to the ABNF notion that the DID is just the scheme, method, and id string, have documented, in the spec, usage that runs contrary to that. In your own PR, you have the text "DIDs that include DID fragments". By your own voice, @dmitrizagidulin, DIDs clearly include the fragment part if specified. You can't have it both ways.

Another problem with the spec and in our conversations, is the extremely uneven and inconsistent treatment of fragments, queries, and paths. To wit, the definitions section says the following:

DID Fragment
The portion of a DID reference that follows the first hash sign character ("#"). A DID fragment uses the same syntax as a URI fragment. See section 5.5. Note that a DID fragment MUST immediately follow a DID. If a DID reference includes a DID path followed by a fragment, that fragment is NOT a DID fragment.
DID Path
The portion of a DID reference that follows the first forward slash character. A DID path uses the identical syntax as a URI path. See section 5.4. Note that if a DID path is followed by a fragment, that fragment is NOT a DID fragment.

None of the current ABNFs support that, nor do anyone's arguments to date support it. Clearly, there is much still to be teased out in this thing about fragments and paths and queries.

This suggests to me that we ran to an ABNF without clearly documenting the requirements and usage that the ABNF should support. As a result, we're arguing syntax when we still have question of semantics.

For example, one thing that came out on the call today is a hidden requirement that DIDs MUST be able to pass through the path, query, and fragment components to the service endpoint. Your comment above stated that clearly, but nowhere has that been communicated as a fundamental purpose of DIDs.

If there's agreement on that, great. I can support it. But it is currently not explained as a primary requirement. Instead it comes up in minor sections, which because of the overall inconsistency like the definitions I quote above, not only rarely get seen, they aren't understood.

As for the feature itself, it seems extremely problematic.

Without inspecting the DID document, one can't even know what kind of resource is expected at the end of that service endpoint, much less whether or not the service endpoint ALREADY has a query, path, or fragment term.

Given a DID did:ex:xyz and a service endpoint like the following in the DID Document:

"service": [{
    "id": "secretmsg",
    "type": "blindedservice",
    "serviceEndpoint": "https://blinded.example.com/974634?src=did%3Aexample%3Axyz%23secretmsg"
  },

Then how does this query/path/fragment stuff work?

If I then try to dereference a DID URI like
did:ex:xyz;secretmsg/94156?src=did%3fake%3did

Then what do you do?

Do you just clobber the path? Override the query term? Include both query terms?

The service endpoint can be ANY valid URI, and as such can include paths and queries and fragments. Attempting to allow DID URI paths, queries, and fragments to "pass through" to the service endpoint is inviting collisions.

This is not how URIs work.

You will break the web.

I'm beginning to see some of the backstory of where previous identity architectures failed to reach consensus at W3C. This magic aggregation is almost certainly a bad idea.

Consider two use cases.

First, the app running on the other side of the request (in a browser, in server side code, etc.) just wants to retrieve the resource specified by the service endpoint. So, with the example above,
did:ex:xyz;secretmsg directly derefrences https://blinded.example.com/974634?src=did%3Aexample%3Axyz%23secretmsg

The caller doesn't know what type it is, what additional parameters there are, or what path there might be. They just want to get to the resource declared in the service endpoint.

In this direct dereference, it would be unwise to encourage additional paths, queries, and fragments because, fundamentally, the caller never sees the details and can't predict how applying such parts to the service endpoint may or may not work. In fact, the exact same DID URI can point to different service endpoints over its lifetime, perhaps switching from facebook to mastodon or from a non-secured http service to an https. It is fundamental to the DID design that these endpoints are going to change even when specified by the same id.

IMO, the semantics of this should be no different than an http redirect. You start with a did with a service component, then you end up with the resource at the specified service endpoint. No merging, no passing the queries or paths or fragments along.

For the second use case, consider an app that is directly driving the resolution and dereferencing. This might be the user-agent, it might be an in-browser app, it might be native code running on a mobile or on a server. In this case, the app is going to dereference the DID to the DID Document because it is looking for a compatible service endpoint. It knows what service endpoint types it prefers and it knows how to structure method calls against those endpoints.

In this case, the app will use the type information to "intelligently" do whatever aggregation, substitution, packaging it needs to. There could be SOAP based service endpoints and REST based end points and everything in-between. The point here is that, in this case, the caller is NOT dereferencing the service endpoint immediately. It is resolving the DID Document, then applying its own business rules to that service endpoint which it then dereferences itself.

In neither of these cases do paths and queries and fragments pass blindly from the caller to the service endpoint.

Are you suggesting that service endpoints MUST NOT have paths or queries or fragments? That's not in the spec and I've never heard it suggested.

If you accept that they can, in fact have those components, is there actually a use case where it makes sense to mix those elements from the DID's URI into the service endpoints?

@dmitrizagidulin
Copy link

@jandrieu - as usual, lots of excellent points and questions. I can address a couple of them in a bit, but I just wanted to skip to the important one real quick:

Are you suggesting that service endpoints MUST NOT have paths or queries or fragments?

If you accept that they can, in fact have those components, is there actually a use case where it makes sense to mix those elements from the DID's URI into the service endpoints?

Yeahhh that's a fine question. I'm not quite sure... Let me get back to you on this :)

@jandrieu
Copy link
Contributor Author

jandrieu commented Feb 20, 2019

@dmitrizagidulin Yeah. I think that's the big question: to pass through/aggregate URI components or not. The rest of the issues are "just" syntax.

@dmitrizagidulin
Copy link

dmitrizagidulin commented Feb 20, 2019

@jandrieu Sooo.. yeah, I think you're absolutely right about the implications.

Given that the ability to "pass through" the path, query and fragment to the serviceEndpoint is one of the two main value propositions of DIDs (and I agree, this part is BARELY documented, if at all :) ).

And given that the serviceEndpoint value could be any sort of valid URI, including having its own path & query & fragment, as in your example:

"serviceEndpoint": "https://blinded.example.com/974634?src=did%3Aexample%3Axyz%23secretmsg"

thennnn... the only reasonable implication is... TO FLIP THE TABLE AND DISBAND THE COMMUNITY GROUP :)

No, wait! That's not it, I always get it confused with that.

No, honestly, the only reasonable implication is the following:

a) (in the Data Model spec) We explicitly restrict the value of serviceEndpoints to be bare origins, with no paths / query fragments / hash fragments.
b) AND ALSO (because people will ignore a)), require that the resolution algorithm MUST strip off any existing path, query fragment and hash fragment, that it finds as the serviceEndpoint value, before applying the service reference path, query and fragment. (Yes, this will have to be specified in the DID Resolution spec.)

Because otherwise, like you say, aggregating the paths/queries/fragments would result in madness and broken URLs.

@dmitrizagidulin
Copy link

@talltree I want to also address what you said a few comments above, but I want to ask first - are those ABNF rules formatted right? I'm having a bit of trouble parsing them.

@talltree
Copy link
Contributor

talltree commented Feb 20, 2019 via email

@jandrieu
Copy link
Contributor Author

a) (in the Data Model spec) We explicitly restrict the value of serviceEndpoints to be bare origins, with no paths / query fragments / hash fragments.
b) AND ALSO (because people will ignore a)), require that the resolution algorithm MUST strip off any existing path, query fragment and hash fragment, that it finds as the serviceEndpoint value, before applying the service reference path, query and fragment. (Yes, this will have to be specified in the DID Resolution spec.)

Because otherwise, like you say, aggregating the paths/queries/fragments would result in madness and broken URLs.

And yet, if we restrict service endpoints like that, one can only use the authority part to identify the associated account. Yes, you can do that with old school user@:

authority = [ userinfo "@" ] host [ ":" port ]

Or with custom host names like http://rwot8.eventbrite.com

But, realistically, most user ids in current services are either path or query terms. You literally would not be able to use my github, Twitter, or Facebook accounts as service endpoints.

In short, if you try to pass through these components, you're gonna break the web.

Perhaps more importantly, I expect the TAG, and others, will have a hard time approving such a technique.

I think you have to dereference without substitution by default, and clients that handle their own dereferencing can construct customized endpoints for those they understand. In either case the starting DID can't contain path or query parts that pass through to the service endpoints. Fragments are probably the reverse; they should never be passed to anyone, and may be applied to the resource returned by referencing the service endpoint. They don't pass through as much as get applied after the resource is retrieved.

If that's the case, then path and query parts are free to be used for semantics like restricting the context within a did document with a path to refer to an element structurally, or as I proposed with queries for indicating service dereferencing and the id of the service.

@talltree
Copy link
Contributor

talltree commented Feb 20, 2019 via email

@dmitrizagidulin
Copy link

@talltree Oh! :) I just meant formatting on a github markdown level. But thank you for running it through a validator!

@mwherman2000
Copy link

mwherman2000 commented Feb 20, 2019

if I have a business card with a DID as with my secure email endpoint
did:xyz:abc123?smail, isn't the entire string what someone would, ideally, be able to put into a DID compatible browser and have it just work?

@jandrieu @ChristopherA I believe you're making a bunch of assumptions about how end-users will actually use DIDs and the end-user usability of DID identifiers. All of these examples are way too technical to reach any critical level of adoption. At most, people will somehow figure out how to copy and paste a plain old DID into some sort of contact object that will be passed around. For your scenarios, I predict there will have to be well known/common names for fragments like "emailAddress", "publicKey", etc. No one has really begun to talk about actual end-user UX scenarios until today.

Are we heading back to something that was worse that UUCP "bang path" email addresses from the '60s and 70's? #noway
image

@dmitrizagidulin
Copy link

@jandrieu

But, realistically, most user ids in current services are either path or query terms. You literally would not be able to use my github, Twitter, or Facebook accounts as service endpoints.

Aha, ok. So this is actually also on purpose, part of the design. The serviceEndpoint values absolutely should not have any sort of user id or any other identifiers in them.
For one, that defeats the whole "no PII / least correlateability" privacy-preserving purpose of DIDs. Now, obviously, if somebody uses their own personal domain as a service endpoint, that completely defeats the privacy purpose, but there's nothing we can do about that, on a domain level.

But anyways, so the mechanism is supposed to work like:

service: [
  {
    id: 'hub',  serviceEndpoint: 'https://facebook.com'
  }
]

And then the service reference uri will look like did:xyz:1234;hub/pictures/userpic.png.
The important thing to note here is that regardless of who will be using that service URI (which will resolve to facebook.com), they're going to be using their own out-of-band user info when interacting with it. Like, if I'm using it, I'll log in to FB as myself. If the link is for other people to use, they're going to be using their own login status and permissions and so on.

Does that make sense?

@jandrieu
Copy link
Contributor Author

@mwherman2000 That's exactly my point. End users won't distinguish between DIDs and DID URIs as defined in the current ABNF. They are all DIDs. Btw, I recommend you read up on my work on Joram and Amira in the RWOT archives. Quite a lot more work has gone into UX than you're giving credit for.

I'm also not sure what the bang path thing is about. No one has recommended that. In fact, I'm trying to simplify the ABNF because (1) we can't safely pass all paths and queries to service endpoints and (2) instead let's use the query part for the service is instead of jamming it onto the hier part with a semicolon.

@dmitrizagidulin
Copy link

instead let's use the query part for the service is instead of jamming it onto the hier part with a semicolon.

So, that's an option that has been brought up multiple times, and rejected. For one, as @talltree and @peacekeeper have mentioned, they've tried that with previous architectures and ran into serious troubles.

Moreover, this approach goes against the URI spec. Query parameters (see Section 3.4 of the URI spec) are scoped to a particular scheme and naming authority. In other words, query parameters are only meaningful to a given server, and have no universal meaning across different URIs (even within the same URI scheme). Similarly, with hash fragments: fragment's format and resolution is dependent on the media type and Fragment identifier semantics are independent of the URI scheme and thus cannot be redefined by scheme specifications. Which means it's not possible (within the spirit of the spec) to "reserve" a service query parameter, in the way that you're thinking.

@mwherman2000
Copy link

End users won't distinguish between DIDs and DID URIs as defined in the current ABNF. They are all DIDs.

@jandrieu This point-of-view continues to be a fundamental problem. Not all DID URIs are "DID"s ...re-read the grammar. I'm not going to say anything more on this.

CC: @talltree @peacekeeper @dmitrizagidulin

@jandrieu
Copy link
Contributor Author

jandrieu commented Feb 20, 2019

@dmitrizagidulin That's a non-starter. While you might try to get folks to avoid PII in the DID Document, you can't prevent it, which means it WILL happen.

But also, this doesn't make sense:

The important thing to note here is that regardless of who will be using that service URI (which will resolve to facebook.com), they're going to be using their own out-of-band user info when interacting with it. Like, if I'm using it, I'll log in to FB as myself. If the link is for other people to use, they're going to be using their own login status and permissions and so on.

The point is that the DID controller is saying you can reach me here, which needs an identifier.

If I stick that facebook endpoint into my DID Document--without any identifier of my account there--you WILL NOT be able to reach me or my Facebook account without already knowing some other detail and knowing how to format those details to get Facebook to direct you to my profile. In short, that's a useless endpoint.

The future of service endpoints is to use the DID identifier as the identifier at the service endpoint to find me. THAT's the PII appropriate way to do that. Just put the DID id in the service endpoint, with whatever formatting it requires. We can do that RIGHT NOW with a service endpoint like:

service: [
  {
    id: "hub",  type: "DidSocial1_0_0", serviceEndpoint: "https://facebook.com/did%3Aex%3Axyz"
  }
]

or

service: [
  {
    id: "hub",  type: "DidSocial1_0_0", serviceEndpoint: "https://example.com/user=%3Aex%3Axyz"
  }
]

This is what endpoints should look like. And the current pass-through feature can't handle that.

And yet, it will be a long time before that happens universally. Instead, people will put both insecure and legacy service endpoints. If the spec can't handle the transition from current to best practices, it'll never make it through TAG review.

@jandrieu
Copy link
Contributor Author

@mwherman2000 That's my point. The grammar is wrong. Despite @talltree and @dmitrizagidulin's assertions to the contrary, their own language in the spec consistently refers to DIDs with fragments. The idea that DIDs are only the scheme, method, and id-string is a figment of ABNF fantasy.

@dmitrizagidulin
Copy link

@jandrieu heh, ignore the language in the spec :) That was cobbled together from many PRs by different people. Let's focus on the underlying issues here -- that we need URIs for a handful of different things, and we need to figure out what to call them / brand them as.
We'll make the language consistent, and fix the ABNF, once we have consensus on the core idea.

@jandrieu
Copy link
Contributor Author

@dmitrizagidulin And yet, that's the best example, in the spec editors own voice, of exactly how the term is and will be used, both how we have been speaking of them and how others will be speaking of them, pretty much no matter what we say to the contrary.

As long as we say DIDs are URIs or URLs, people will expect that the entire string is the DID. Because that is how all other URIs work. The URI is the whole string, full stop. The syntax varies, the semantics vary, but one doesn't refer to just the hier-part of a URL as the URL while the combined string is the URL URI. NOBODY does that.

The only way out of that would be to shift the language dramatically to make it clear that what we are standardizing is not just the DID, but something else, name TBD. And that that thing is a URI. DIDs are just a part of that. But, I would bet my co-chair of this committee that you aren't going to get that by the consensus. It's too powerful and too resonant to say DIDs are a new URI. THAT has become canon and will be nearly impossible to change.

@jandrieu
Copy link
Contributor Author

Moreover, this approach goes against the URI spec. Query parameters (see Section 3.4 of the URI spec) are scoped to a particular scheme and naming authority. In other words, query parameters are only meaningful to a given server, and have no universal meaning across different URIs (even within the same URI scheme). Similarly, with hash fragments: fragment's format and resolution is dependent on the media type and Fragment identifier semantics are independent of the URI scheme and thus cannot be redefined by scheme specifications. Which means it's not possible (within the spirit of the spec) to "reserve" a service query parameter, in the way that you're thinking.

Hmmm. I read that with exactly the opposite conclusion. Query parameters are scoped to the scheme, aka "did" and naming authority aka the method and the id string. If you review my mapping of the URI generic scheme, the authority part is the method:id-string part. Which means queries are scoped to the DID Document, meaning any DID Document can define its own query terms.

Just because URL authority parts usually resolve to servers doesn't mean that authority === server. Quite the contrary, from 3986 section 3.2:

The generic syntax provides a common
means for distinguishing an authority based on a registered name or
server address, along with optional port and user information.

Yes. We use the authority part to distinguish based on a registered name (instead of a server address). That name is registered within a namespace defined by the method. Together, method+id-string fully meet the non-server expectations of an authority.

You may note that the authority part used to be called the server part. That's deprecated, but I can see where your expectation comes from. However, it's clear that the authority part was clarified to mean exactly how we use it: to specify the scope of the namespace for an identifier.

@dmitrizagidulin
Copy link

Ok, so, maybe a call or an in-person discussion might be higher bandwidth, at this point. (I apologize for dragging out the discussion on this GH issue) :) My main aim was to use the fact that github displays code snippets nicely (so I could list the various URIs that we'll need to name and put into the ABNF), so we don't have to draw them on a whiteboard or whatever.

@jandrieu
Copy link
Contributor Author

Indeed. RWOT is right around the corner.

FWIW, no need to apologize for "dragging out the discussion" here. That's what issues are for. Although I do apologize for other readers. It's hard to sync up with the back-and-forth.

@ChristopherA
Copy link
Contributor

ChristopherA commented Feb 20, 2019

I believe you're making a bunch of assumptions about how end-users will actually use DIDs and the end-user usability of DID identifiers. All of these examples are way too technical to reach any critical level of adoption.

a) my hope is that we get to the point that end-users rarely if ever see DIDs, just as they today don't see IP addresses in URLs. Instead, the work from previous #RebootingWebOfTrust on the topic of local names / pet names / etc. will advance. I personally believe for DIDs it will largely work the way phone numbers work for younger generation today — they never see them, they just save on first use and name them to an address book, or pass them on to someone else as an attachment. At best, they memorize their own (which my experience with younger generation they don't even remember their own phone number, they have to look it up on their phone).

b) Our audience isn't end-users, its developers. Almost all of these advanced features will rarely be used for end-user DIDs, but to allow apps to communicate with apps about more specific thing they need, the way that phone numbers today can use * and # that the larger system understands as well as + as a shortcut for international , for pause and ; for break that most phones understand. The best conferencing services now use these extra symbols for logging on to a meeting. It will be similar for DIDs, end-users will use them or bookmark them, but don't need to understand them.

@talltree
Copy link
Contributor

talltree commented Feb 20, 2019 via email

@talltree
Copy link
Contributor

talltree commented Feb 20, 2019 via email

@talltree
Copy link
Contributor

talltree commented Feb 20, 2019 via email

@mwherman2000
Copy link

mwherman2000 commented Feb 22, 2019

did-fragment-ref = "#" fragment 
did-service-ref = *( ";" service-id ) [ path-abempty ] [ "?" query ] [ "#" fragment ]

Can someone clarify/simmarize what a "fragment" is in the context of a DID Document ? ...that is, a more detailed explanation beyond a fragment is something that is dereferencible.

For example, if you have did:xyz:1234#foo, how does a DID resolver know if it is supposed to dereference a key vs. an service endpoint vs. something else in the DID Document? ...perhaps, using https://w3c-ccg.github.io/did-spec/#real-world-example as a context for the explanation.

@talltree
Copy link
Contributor

talltree commented Feb 23, 2019 via email

@jandrieu
Copy link
Contributor Author

@talltree said

When you apply that DID documents, the use of a DID fragment is "the identification of a secondary resource" within the DID document.

This is not true if there is a service endpoint in the DID. In that case, the fragment applies to the resource returned by the endpoint bout the DID document.

The fragment applies within whatever resource is retrieved by dereferencing, NOT by resolving. Others have expressed confusion over this point as well.

I think the conflation of dereferencing and resolving is at the heart of much confusion and error in the spec. I recommend restricting resolving to return the entire DID Document, and allow the user agent to apply the fragment reference. The fragment is not designed to be passed upstream.

@talltree
Copy link
Contributor

talltree commented Feb 24, 2019 via email

@jandrieu
Copy link
Contributor Author

jandrieu commented Feb 24, 2019

My point is that you were unclear, so if you think you got it figured out on the call, you need to try again.

The answer to @mwherman2000 is that if there is a service reference, the fragment applies to the resource retrieved by the service endpoint. Otherwise, it will be applied to the DID Document.

@mwherman2000
Copy link

The answer to @mwherman2000 is that if there is a service reference, the fragment applies to the resource retrieved by the service endpoint. Otherwise, it will be applied to the DID Document.

@jandrieu How do you dereference a component of a DID Document when there is a service endpoint? ...for example, how do you dereference the URI/URL of the service endpoint itself?

@talltree
Copy link
Contributor

talltree commented Feb 25, 2019 via email

@mwherman2000
Copy link

mwherman2000 commented Feb 25, 2019

This is not true if there is a service endpoint in the DID.

My apologies for forgetting to not respond to any further abuses of the term "DID".

Further, the name of the token that follows a ";" is a service-id (at least that is what it is called in both @talltree and @dmitrizagidulin 's recent versions of the DID ABNF grammar). More importantly, it's not a service endpoint ...in addition to it not being part of a DID.

@mwherman2000
Copy link

mwherman2000 commented Feb 25, 2019

In EXAMPLE 16 (reproduced below):

  1. How and where can dereferencable "anchors" be placed inside a DID document? (this question has nothing to do with the DID ABNF ...just the structure of a DID Document):
    a. for locating public keys? for example, is it anywhere there is a #foo construct in a publicKey id attribute?
    b. for locating service endpoints? for example, is it anywhere there is a ;bar construct in a service id attribute?
    c. are there any other scenarios? ...any other delimiters in addition to # and ;?

EXAMPLE 16: Advanced DID Document example

{
  "@context": "https://w3id.org/future-method/v1",
  "id": "did:example:123456789abcdefghi",

  "publicKey": [{
    "id": "did:example:123456789abcdefghi#keys-1",
    "type": "RsaVerificationKey2018",
    "controller": "did:example:123456789abcdefghi",
    "publicKeyPem": "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
  }, {
    "id": "did:example:123456789abcdefghi#keys-3",
    "type": "Ieee2410VerificationKey2018",
    "controller": "did:example:123456789abcdefghi",
    "publicKeyPem": "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
  }],

  "authentication": [
    // this mechanism can be used to authenticate as did:...fghi
    "did:example:123456789abcdefghi#keys-1",
    // this mechanism can be used to biometrically authenticate as did:...fghi
    "did:example:123456789abcdefghi#keys-3",
    // this mechanism is *only* authorized for authentication, it may not
    // be used for any other proof purpose, so its full description is
    // embedded here rather than using only a reference
    {
      "id": "did:example:123456789abcdefghi#keys-2",
      "type": "Ed25519VerificationKey2018",
      "controller": "did:example:123456789abcdefghi",
      "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
    }
  ],

  "service": [{
    "type": "OpenIdConnectVersion1.0Service",
    "serviceEndpoint": "https://openid.example.com/"
  }, {
    "type": "CredentialRepositoryService",
    "serviceEndpoint": "https://repository.example.com/service/8377464"
  }, {
    "type": "XdiService",
    "serviceEndpoint": "https://xdi.example.com/8377464"
  }, {
    "type": "HubService",
    "serviceEndpoint": "https://hub.example.com/.identity/did:example:0123456789abcdef/"
  }, {
    "type": "MessagingService",
    "serviceEndpoint": "https://example.com/messages/8377464"
  }, {
    "type": "SocialWebInboxService",
    "serviceEndpoint": "https://social.example.com/83hfh37dj",
    "description": "My public social inbox",
    "spamCost": {
      "amount": "0.50",
      "currency": "USD"
    }
  }, {
    "type": "DidAuthPushModeVersion1",
    "serviceEndpoint": "http://auth.example.com/did:example:123456789abcdefghi"
  }, {
    "id": "did:example:123456789abcdefghi;bops",
    "type": "BopsService",
    "serviceEndpoint": "https://bops.example.com/enterprise/"
  }]
}

@talltree
Copy link
Contributor

talltree commented Feb 25, 2019 via email

@mwherman2000
Copy link

mwherman2000 commented Feb 25, 2019

@talltree Based on your reply, please confirm that the following 4 examples for the 3 use cases are correct:

Example A: Use case 1a from above: In the following snippet from EXAMPLE 16...

  "publicKey": [{
    "id": "did:example:123456789abcdefghi#keys-1",
    "type": "RsaVerificationKey2018",
    "controller": "did:example:123456789abcdefghi",
    "publicKeyPem": "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
  }, {
    "id": "did:example:123456789abcdefghi#keys-3",
    "type": "Ieee2410VerificationKey2018",
    "controller": "did:example:123456789abcdefghi",
    "publicKeyPem": "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
  }]
  • did:example:123456789abcdefghi#keys-1 will dereference to the following specific JSON string (no less and no more)?
{
    "id": "did:example:123456789abcdefghi#keys-1",
    "type": "RsaVerificationKey2018",
    "controller": "did:example:123456789abcdefghi",
    "publicKeyPem": "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
  }
  • if #keys-1 was used as is (without further qualification) elsewhere inside the EXAMPLE 16 DID Document, it would dereference to the above same JSON string (NLANM)?

Example B: Another use case 1a example: In the following snippet from EXAMPLE 16...

  "authentication": [
    "did:example:123456789abcdefghi#keys-1",
    "did:example:123456789abcdefghi#keys-3",
    {
      "id": "did:example:123456789abcdefghi#keys-2",
      "type": "Ed25519VerificationKey2018",
      "controller": "did:example:123456789abcdefghi",
      "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
    }
  ],
  • did:example:123456789abcdefghi#keys-2 will dereference to the following specific JSON string (no less and no more)?
    {
      "id": "did:example:123456789abcdefghi#keys-2",
      "type": "Ed25519VerificationKey2018",
      "controller": "did:example:123456789abcdefghi",
      "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
    }
  • if #keys-2 was used as is (without further qualification) elsewhere inside the EXAMPLE 16 DID Document, it would dereference to the above same JSON string (NLANM)?

Example C: Use case 1b from above: In the following snippet from EXAMPLE 16...

  "service": [
... 
  {
    "id": "did:example:123456789abcdefghi;bops",
    "type": "BopsService",
    "serviceEndpoint": "https://bops.example.com/enterprise/"
  }]
  • did:example:123456789abcdefghi;bops will dereference to the following specific JSON string (no less and no more)?
  {
    "id": "did:example:123456789abcdefghi;bops",
    "type": "BopsService",
    "serviceEndpoint": "https://bops.example.com/enterprise/"
  }
  • if ;bops was used as is (without further qualification) elsewhere inside the EXAMPLE 16 DID Document, it would dereference to the above same JSON string (NLANM)?

Example D: Use case 1c "Other scenarios": If I added the following hypothetical extension to EXAMPLE 16:

{
  "@context": "https://example.org/example-method/v1",
  "id": "did:example:123456789abcdefghi",

  "authentication": [ ... ],

  "service": [ ... ],

  "thingamajig": [{
        "@context": "did:example:things:987654321",
        "id": "did:example:123456789abcdefghi#thing-1",
        ...
  }]
}
  • did:example:123456789abcdefghi#thing-1 will dereference to the following specific JSON string (no less and no more)?
{
        "@context": "did:example:things:987654321",
        "id": "did:example:123456789abcdefghi#thing-1",
        ...
  }
  • if #thing-1 was used as is (without further qualification) elsewhere inside the extended EXAMPLE 16 DID Document, it would dereference to the above same JSON string (NLANM)?

@talltree
Copy link
Contributor

talltree commented Feb 26, 2019 via email

@jonnycrunch
Copy link

So, why not just use "/" as a path to the inside of the DID document?

If I understand the ABNF, after the DID URl would be separated from the naked DID with any character not :, ., -, so ; or/. While # would work, i'd like to reserve this for client side stuff.

In the IPID DID method, we are reserving the '#' for a decryption key, because as @ChristopherA mentioned above, and as in the www URI, it is NOT supposed to be sent to the server and instead is parsed locally.

According to https://www.ietf.org/rfc/rfc3986.txt:

3.5. Fragment

The fragment identifier component of a URI allows indirect
identification of a secondary resource by reference to a primary
resource and additional identifying information. The identified
secondary resource may be some portion or subset of the primary
resource, some view on representations of the primary resource, or
some other resource defined or described by those representations. A
fragment identifier component is indicated by the presence of a
number sign ("#") character and terminated by the end of the URI.

fragment = *( pchar / "/" / "?" )

The semantics of a fragment identifier are defined by the set of
representations that might result from a retrieval action on the
primary resource. The fragment's format and resolution is therefore
dependent on the media type [RFC2046] of a potentially retrieved
representation
, even though such a retrieval is only performed if the
URI is dereferenced.
* If no such representation exists, then the
semantics of the fragment are considered unknown and are effectively
unconstrained. Fragment identifier semantics are independent of the
URI scheme and thus cannot be redefined by scheme specifications.

Individual media types may define their own restrictions on or
structures within the fragment identifier syntax for specifying
different types of subsets, views, or external references that are
identifiable as secondary resources by that media type. If the
primary resource has multiple representations, as is often the case
for resources whose representation is selected based on attributes of
the retrieval request (a.k.a., content negotiation), then whatever is
identified by the fragment should be consistent across all of those
representations. Each representation should either define the
fragment so that it corresponds to the same secondary resource,
regardless of how it is represented, or should leave the fragment
undefined (i.e., not found).

@mwherman2000
Copy link

@jonnycrunch Can you provide some examples? ....perhaps related to the use cases in w3c/did-resolution#32?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
discuss Wider discussion in an issue or meeting required before merging
Projects
None yet
8 participants